diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/schema.rs | 26 | ||||
-rw-r--r-- | src/static_api.rs | 13 | ||||
-rw-r--r-- | src/validate.rs | 29 |
3 files changed, 68 insertions, 0 deletions
diff --git a/src/schema.rs b/src/schema.rs index 570b212..779e86c 100644 --- a/src/schema.rs +++ b/src/schema.rs @@ -7,12 +7,17 @@ use std::collections::HashSet; #[serde(deny_unknown_fields, rename_all = "kebab-case")] pub(crate) struct Config { allowed_mailing_lists_domains: HashSet<String>, + allowed_github_orgs: HashSet<String>, } impl Config { pub(crate) fn allowed_mailing_lists_domains(&self) -> &HashSet<String> { &self.allowed_mailing_lists_domains } + + pub(crate) fn allowed_github_orgs(&self) -> &HashSet<String> { + &self.allowed_github_orgs + } } // This is an enum to allow two kinds of values for the email field: @@ -108,6 +113,7 @@ pub(crate) struct Team { people: TeamPeople, #[serde(default)] permissions: Permissions, + github: Option<GitHubData>, rfcbot: Option<RfcbotData>, website: Option<WebsiteData>, #[serde(default)] @@ -213,6 +219,19 @@ impl Team { pub(crate) fn permissions(&self) -> &Permissions { &self.permissions } + + pub(crate) fn github_teams(&self) -> Vec<(&str, &str)> { + if let Some(github) = &self.github { + let name = github + .name + .as_ref() + .map(|n| n.as_str()) + .unwrap_or(&self.name); + github.orgs.iter().map(|org| (org.as_str(), name)).collect() + } else { + Vec::new() + } + } } #[derive(serde_derive::Deserialize, Debug)] @@ -228,6 +247,13 @@ struct TeamPeople { include_all_team_members: bool, } +#[derive(serde::Deserialize, Debug)] +#[serde(rename_all = "kebab-case", deny_unknown_fields)] +struct GitHubData { + name: Option<String>, + orgs: Vec<String>, +} + #[derive(serde_derive::Deserialize, Debug)] #[serde(rename_all = "kebab-case", deny_unknown_fields)] pub(crate) struct RfcbotData { diff --git a/src/static_api.rs b/src/static_api.rs index 15e1dcd..3760b4e 100644 --- a/src/static_api.rs +++ b/src/static_api.rs @@ -48,6 +48,9 @@ impl<'a> Generator<'a> { members.sort_by_key(|member| member.github.to_lowercase()); members.sort_by_key(|member| !member.is_lead); + let mut github_teams = team.github_teams(); + github_teams.sort(); + let team_data = v1::Team { name: team.name().into(), kind: if team.is_wg() { @@ -57,6 +60,16 @@ impl<'a> Generator<'a> { }, subteam_of: team.subteam_of().map(|st| st.into()), members, + github: Some(v1::TeamGitHub { + teams: github_teams + .iter() + .map(|(org, name)| v1::GitHubTeam { + org: org.to_string(), + name: name.to_string(), + }) + .collect::<Vec<_>>(), + }) + .filter(|gh| !gh.teams.is_empty()), website_data: team.website_data().map(|ws| v1::TeamWebsite { name: ws.name().into(), description: ws.description().into(), diff --git a/src/validate.rs b/src/validate.rs index 4c4ebfb..e33f391 100644 --- a/src/validate.rs +++ b/src/validate.rs @@ -23,6 +23,7 @@ static CHECKS: &[fn(&Data, &mut Vec<String>)] = &[ validate_rfcbot_labels, validate_rfcbot_exclude_members, validate_team_names, + validate_github_teams, ]; static GITHUB_CHECKS: &[fn(&Data, &GitHubApi, &mut Vec<String>)] = &[validate_github_usernames]; @@ -381,6 +382,34 @@ fn validate_team_names(data: &Data, errors: &mut Vec<String>) { }); } +/// Ensure GitHub teams are unique and in the allowed orgs +fn validate_github_teams(data: &Data, errors: &mut Vec<String>) { + let mut found = HashMap::new(); + let allowed = data.config().allowed_github_orgs(); + wrapper(data.teams(), errors, |team, errors| { + wrapper(team.github_teams().into_iter(), errors, |(org, name), _| { + if !allowed.contains(&*org) { + bail!( + "GitHub organization `{}` isn't allowed (in team `{}`)", + org, + team.name() + ); + } + if let Some(other) = found.insert((org, name), team.name()) { + bail!( + "GitHub team `{}/{}` is defined for both the `{}` and `{}` teams", + org, + name, + team.name(), + other + ); + } + Ok(()) + }); + Ok(()) + }); +} + /// Ensure there are no misspelled GitHub account names fn validate_github_usernames(data: &Data, github: &GitHubApi, errors: &mut Vec<String>) { let people = data |