summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPietro Albini <pietro@pietroalbini.org>2019-07-17 12:06:29 +0200
committerPietro Albini <pietro@pietroalbini.org>2019-07-17 12:06:29 +0200
commit9c657f238d9a1354536dcb0a2e89adf5dd6cef4b (patch)
treea2269b492fe462fb09a09ee89e453a07f4c30b71
parent732feec5e8db47846ae2fbfe69fbf028090a809d (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.toml5
-rw-r--r--docs/toml-schema.md6
-rw-r--r--rust_team_data/src/v1.rs12
-rw-r--r--src/schema.rs26
-rw-r--r--src/static_api.rs13
-rw-r--r--src/validate.rs29
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