Skip to content

Commit

Permalink
Merge pull request #1576 from Kobzol/merge-bot
Browse files Browse the repository at this point in the history
Add `merge-bots` configuration per branch protection
  • Loading branch information
MarcoIeni authored Nov 19, 2024
2 parents d1f57e2 + a5231d3 commit 012c44a
Show file tree
Hide file tree
Showing 8 changed files with 58 additions and 14 deletions.
8 changes: 8 additions & 0 deletions docs/toml-schema.md
Original file line number Diff line number Diff line change
Expand Up @@ -352,4 +352,12 @@ required-approvals = 1
# can push/merge to the branch.
# (optional)
allowed-merge-teams = ["awesome-team"]
# Determines the merge queue bot(s) that manage pushes to this branch.
# When a bot manages the queue, some other options, like
# `required-approvals` and `pr-required` options are not valid.
#
# Currently, only the "homu" option is supported.
# When "homu" is used, "bors" has to be in the `bots` array.
# (optional)
merge-bots = ["homu"]
```
7 changes: 7 additions & 0 deletions rust_team_data/src/v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,12 +219,19 @@ pub enum BranchProtectionMode {
PrNotRequired,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "snake_case")]
pub enum MergeBot {
Homu,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct BranchProtection {
pub pattern: String,
pub dismiss_stale_review: bool,
pub mode: BranchProtectionMode,
pub allowed_merge_teams: Vec<String>,
pub merge_bots: Vec<MergeBot>,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
Expand Down
8 changes: 8 additions & 0 deletions src/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -787,6 +787,12 @@ pub(crate) enum RepoPermission {
Admin,
}

#[derive(serde_derive::Deserialize, Debug, PartialEq, Eq)]
#[serde(rename_all = "kebab-case")]
pub(crate) enum MergeBot {
Homu,
}

#[derive(serde_derive::Deserialize, Debug)]
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
pub(crate) struct BranchProtection {
Expand All @@ -801,4 +807,6 @@ pub(crate) struct BranchProtection {
pub pr_required: bool,
#[serde(default)]
pub allowed_merge_teams: Vec<String>,
#[serde(default)]
pub merge_bots: Vec<MergeBot>,
}
11 changes: 10 additions & 1 deletion src/static_api.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use crate::data::Data;
use crate::schema::{Bot, Email, Permissions, RepoPermission, TeamKind, ZulipGroupMember};
use crate::schema::{
Bot, Email, MergeBot, Permissions, RepoPermission, TeamKind, ZulipGroupMember,
};
use anyhow::{ensure, Context as _, Error};
use indexmap::IndexMap;
use log::info;
Expand Down Expand Up @@ -59,6 +61,13 @@ impl<'a> Generator<'a> {
BranchProtectionMode::PrNotRequired
},
allowed_merge_teams: b.allowed_merge_teams.clone(),
merge_bots: b
.merge_bots
.iter()
.map(|bot| match bot {
MergeBot::Homu => v1::MergeBot::Homu,
})
.collect(),
})
.collect();
let managed_by_bors = r.bots.contains(&Bot::Bors);
Expand Down
26 changes: 17 additions & 9 deletions src/validate.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use crate::data::Data;
use crate::github::GitHubApi;
use crate::schema::{Bot, Email, Permissions, Team, TeamKind, TeamPeople, ZulipGroupMember};
use crate::schema::{
Bot, Email, MergeBot, Permissions, Team, TeamKind, TeamPeople, ZulipGroupMember,
};
use crate::zulip::ZulipApi;
use anyhow::{bail, Error};
use log::{error, warn};
Expand Down Expand Up @@ -824,7 +826,8 @@ fn validate_branch_protections(data: &Data, errors: &mut Vec<String>) {
let github_teams = data.github_teams();

wrapper(data.repos(), errors, |repo, _| {
let bors_used = repo.bots.iter().any(|b| matches!(b, Bot::Bors));
let homu_configured = repo.bots.iter().any(|b| matches!(b, Bot::Bors));

for protection in &repo.branch_protections {
for team in &protection.allowed_merge_teams {
let key = (repo.org.clone(), team.clone());
Expand Down Expand Up @@ -858,19 +861,24 @@ but that team does not seem to exist"#,
}
}

if bors_used {
if protection.required_approvals.is_some() {
let managed_by_homu = protection.merge_bots.contains(&MergeBot::Homu);
if managed_by_homu {
if !homu_configured {
bail!(
r#"repo '{}' uses bors and its branch protection for {} uses the `required-approvals` attribute;
please remove the attribute when using bors"#,
r#"repo '{}' uses homu to manage a branch protection for '{}', but homu is not enabled. Add "bors" to the `bots` array"#,
repo.name,
protection.pattern,
);
}
if !protection.allowed_merge_teams.is_empty() {
if protection.required_approvals.is_some()
|| protection.dismiss_stale_review
|| !protection.pr_required
|| !protection.allowed_merge_teams.is_empty()
{
bail!(
r#"repo '{}' uses bors and its branch protection for {} uses the `allowed-merge-teams` attribute;
please remove the attribute when using bors"#,
r#"repo '{}' uses the homu merge bot, but its branch protection for {} uses invalid
attributes (`required-approvals`, `dismiss-stale-review`, `pr-required` or `allowed-merge-teams`).
Please remove the attributes when using bors"#,
repo.name,
protection.pattern,
);
Expand Down
6 changes: 4 additions & 2 deletions tests/static-api/_expected/v1/repos.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
"required_approvals": 1
}
},
"allowed_merge_teams": []
"allowed_merge_teams": [],
"merge_bots": []
}
],
"archived": true,
Expand Down Expand Up @@ -59,7 +60,8 @@
},
"allowed_merge_teams": [
"foo"
]
],
"merge_bots": []
}
],
"archived": false,
Expand Down
3 changes: 2 additions & 1 deletion tests/static-api/_expected/v1/repos/archived_repo.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
"required_approvals": 1
}
},
"allowed_merge_teams": []
"allowed_merge_teams": [],
"merge_bots": []
}
],
"archived": true,
Expand Down
3 changes: 2 additions & 1 deletion tests/static-api/_expected/v1/repos/some_repo.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
},
"allowed_merge_teams": [
"foo"
]
],
"merge_bots": []
}
],
"archived": false,
Expand Down

0 comments on commit 012c44a

Please sign in to comment.