diff options
author | Pietro Albini <pietro@pietroalbini.org> | 2019-07-17 12:06:29 +0200 |
---|---|---|
committer | Pietro Albini <pietro@pietroalbini.org> | 2019-07-17 12:06:29 +0200 |
commit | 9c657f238d9a1354536dcb0a2e89adf5dd6cef4b (patch) | |
tree | a2269b492fe462fb09a09ee89e453a07f4c30b71 | |
parent | 732feec5e8db47846ae2fbfe69fbf028090a809d (diff) |
add github teams in the schema and the api
This will allow synchronization tools for GitHub teams to be built. No
teams are currently configured to be synchronized.
-rw-r--r-- | config.toml | 5 | ||||
-rw-r--r-- | docs/toml-schema.md | 6 | ||||
-rw-r--r-- | rust_team_data/src/v1.rs | 12 | ||||
-rw-r--r-- | src/schema.rs | 26 | ||||
-rw-r--r-- | src/static_api.rs | 13 | ||||
-rw-r--r-- | src/validate.rs | 29 |
6 files changed, 91 insertions, 0 deletions
diff --git a/config.toml b/config.toml index e62c24b..5159efb 100644 --- a/config.toml +++ b/config.toml @@ -3,3 +3,8 @@ allowed-mailing-lists-domains = [ "crates.io", "docs.rs", ] + +allowed-github-orgs = [ + "rust-lang", + "rust-lang-nursery", +] diff --git a/docs/toml-schema.md b/docs/toml-schema.md index 208ceed..0147d6d 100644 --- a/docs/toml-schema.md +++ b/docs/toml-schema.md @@ -45,6 +45,12 @@ members = [ [permissions] # Optional, see the permissions documentation +# Configure the GitHub integration +# This is optional, and if missing the team won't be synchronized with GitHub +[github] +name = "overlords-team" # The name of the GitHub team (optional) +orgs = ["rust-lang"] # Organizations to create the team in (required) + # Define the mailing lists used by the team # It's optional, and there can be more than one [[lists]] diff --git a/rust_team_data/src/v1.rs b/rust_team_data/src/v1.rs index 839c66d..b582f4f 100644 --- a/rust_team_data/src/v1.rs +++ b/rust_team_data/src/v1.rs @@ -16,6 +16,7 @@ pub struct Team { pub kind: TeamKind, pub subteam_of: Option<String>, pub members: Vec<TeamMember>, + pub github: Option<TeamGitHub>, pub website_data: Option<TeamWebsite>, } @@ -28,6 +29,17 @@ pub struct TeamMember { } #[derive(Debug, Clone, Serialize, Deserialize)] +pub struct TeamGitHub { + pub teams: Vec<GitHubTeam>, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct GitHubTeam { + pub org: String, + pub name: String, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct TeamWebsite { pub name: String, pub description: String, 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 |