collab: Fix GitHub user retrieval in seed script (#18296)

This PR fixes the GitHub user retrieval in the database seed script.

The users returned from the [list
users](https://docs.github.com/en/rest/users/users?apiVersion=2022-11-28#list-users)
endpoint don't have a `created_at` timestamp, so we need to fetch them
individually.

I want to rework this further at a later date, this is just a bandaid to
get things working again.

Release Notes:

- N/A
This commit is contained in:
Marshall Bowers 2024-09-24 15:44:55 -04:00 committed by GitHub
parent 87ac4cff60
commit 692590bff4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 44 additions and 5 deletions

View file

@ -298,6 +298,12 @@ impl Database {
result result
} }
/// Returns all feature flags.
pub async fn list_feature_flags(&self) -> Result<Vec<feature_flag::Model>> {
self.transaction(|tx| async move { Ok(feature_flag::Entity::find().all(&*tx).await?) })
.await
}
/// Creates a new feature flag. /// Creates a new feature flag.
pub async fn create_user_flag(&self, flag: &str, enabled_for_all: bool) -> Result<FlagId> { pub async fn create_user_flag(&self, flag: &str, enabled_for_all: bool) -> Result<FlagId> {
self.transaction(|tx| async move { self.transaction(|tx| async move {

View file

@ -16,13 +16,23 @@ struct GithubUser {
created_at: DateTime<Utc>, created_at: DateTime<Utc>,
} }
/// A GitHub user returned from the [List users](https://docs.github.com/en/rest/users/users?apiVersion=2022-11-28#list-users) endpoint.
///
/// Notably, this data type does not have the `created_at` field.
#[derive(Debug, Deserialize)]
struct ListGithubUser {
id: i32,
login: String,
email: Option<String>,
}
#[derive(Deserialize)] #[derive(Deserialize)]
struct SeedConfig { struct SeedConfig {
// Which users to create as admins. /// Which users to create as admins.
admins: Vec<String>, admins: Vec<String>,
// Which channels to create (all admins are invited to all channels) /// Which channels to create (all admins are invited to all channels).
channels: Vec<String>, channels: Vec<String>,
// Number of random users to create from the Github API /// Number of random users to create from the Github API.
number_of_users: Option<usize>, number_of_users: Option<usize>,
} }
@ -47,11 +57,21 @@ pub async fn seed(config: &Config, db: &Database, force: bool) -> anyhow::Result
let flag_names = ["remoting", "language-models"]; let flag_names = ["remoting", "language-models"];
let mut flags = Vec::new(); let mut flags = Vec::new();
let existing_feature_flags = db.list_feature_flags().await?;
for flag_name in flag_names { for flag_name in flag_names {
if existing_feature_flags
.iter()
.any(|flag| flag.flag == flag_name)
{
log::info!("Flag {flag_name:?} already exists");
continue;
}
let flag = db let flag = db
.create_user_flag(flag_name, false) .create_user_flag(flag_name, false)
.await .await
.unwrap_or_else(|_| panic!("failed to create flag: '{flag_name}'")); .unwrap_or_else(|err| panic!("failed to create flag: '{flag_name}': {err}"));
flags.push(flag); flags.push(flag);
} }
@ -121,9 +141,19 @@ pub async fn seed(config: &Config, db: &Database, force: bool) -> anyhow::Result
if let Some(last_user_id) = last_user_id { if let Some(last_user_id) = last_user_id {
write!(&mut uri, "&since={}", last_user_id).unwrap(); write!(&mut uri, "&since={}", last_user_id).unwrap();
} }
let users = fetch_github::<Vec<GithubUser>>(&client, &uri).await; let users = fetch_github::<Vec<ListGithubUser>>(&client, &uri).await;
for github_user in users { for github_user in users {
log::info!("Seeding {:?} from GitHub", github_user.login);
// Fetch the user to get their `created_at` timestamp, since it
// isn't on the list response.
let github_user: GithubUser = fetch_github(
&client,
&format!("https://api.github.com/user/{}", github_user.id),
)
.await;
last_user_id = Some(github_user.id); last_user_id = Some(github_user.id);
user_count += 1; user_count += 1;
let user = db let user = db
@ -143,6 +173,9 @@ pub async fn seed(config: &Config, db: &Database, force: bool) -> anyhow::Result
flag, user.id flag, user.id
))?; ))?;
} }
// Sleep to avoid getting rate-limited by GitHub.
tokio::time::sleep(std::time::Duration::from_millis(250)).await;
} }
} }
} }