Watch
0
0
Fork
You've already forked hyperhive
0

config repos: drop the hive's branch-protection edit and core from the merge gate

Folds in #4853: hive-c0re no longer writes branch protection on
`agent-configs` repos (apply_config_repo_branch_protection,
config_repo_protection_edit, record_branch_protection_result and the
now-unused main_branch_protection_option go). swarm-controller's
CreateRepo rule and its forge-objects convergence own `main`'s gate.

Nothing merges into config `main` as `core` any more, so the converged
rule's merge user list is empty. `push_config` still pushes `main` as
core, through push rights, not the merge whitelist.

Refs #4850
Refs #4853
This commit is contained in:
atlas 2026-10-02 22:32:17 +02:00
commit 0cee0382e9
3 changed files with 36 additions and 235 deletions

View file

@ -33,7 +33,6 @@ use forgejo_api::{ApiErrorKind, ForgejoError};
use reqwest::StatusCode;
use serde::Deserialize;
use super::legacy_tokens::CORE_USER;
use super::{
CONFIG_ORG, Client, KNOWLEDGE_ORG, KNOWLEDGE_REPO, OPERATORS_TEAM, base64_encode,
folds_into_success, is_ambiguous_validation_failure, is_confirmed_conflict,
@ -523,11 +522,11 @@ fn team_matches(t: &Team) -> bool {
}
/// The merge gate on every config repo's `main`: the `operators` team approves
/// and merges, and `core` merges too, for the hive's dashboard approval.
/// and merges, and no user does. The empty user list removes any user an
/// older rule carries.
///
/// Forgejo replaces each list this sends wholesale and keeps every field left
/// `None`, `required_approvals` included — the hive's own boot PATCH sets
/// that one.
/// `None` as the rule has it, `required_approvals` included.
fn config_rule_edit() -> EditBranchProtectionOption {
EditBranchProtectionOption {
apply_to_admins: None,
@ -544,7 +543,7 @@ fn config_rule_edit() -> EditBranchProtectionOption {
enable_status_check: None,
ignore_stale_approvals: None,
merge_whitelist_teams: Some(vec![OPERATORS_TEAM.to_owned()]),
merge_whitelist_usernames: Some(vec![CORE_USER.to_owned()]),
merge_whitelist_usernames: Some(Vec::new()),
protected_file_patterns: None,
push_whitelist_deploy_keys: None,
push_whitelist_teams: None,
@ -561,7 +560,10 @@ fn config_rule_matches(rule: &BranchProtection) -> bool {
let only = |list: &Option<Vec<String>>, want: &str| matches!(list.as_deref(), Some([entry]) if entry == want);
rule.enable_merge_whitelist == Some(true)
&& only(&rule.merge_whitelist_teams, OPERATORS_TEAM)
&& only(&rule.merge_whitelist_usernames, CORE_USER)
&& rule
.merge_whitelist_usernames
.as_deref()
.is_none_or(<[String]>::is_empty)
&& rule.enable_approvals_whitelist == Some(true)
&& only(&rule.approvals_whitelist_teams, OPERATORS_TEAM)
}
@ -1315,14 +1317,16 @@ mod tests {
}
#[test]
fn a_config_rule_matches_only_with_operators_and_core() {
assert!(config_rule_matches(&rule(&[CORE_USER])));
assert!(!config_rule_matches(&rule(&[])));
assert!(!config_rule_matches(&rule(&[CORE_USER, "mallory"])));
let mut core_only = rule(&[CORE_USER]);
core_only.merge_whitelist_teams = None;
assert!(!config_rule_matches(&core_only));
let mut approvals_off = rule(&[CORE_USER]);
fn a_config_rule_matches_only_with_operators_and_no_user() {
assert!(config_rule_matches(&rule(&[])));
let mut users_absent = rule(&[]);
users_absent.merge_whitelist_usernames = None;
assert!(config_rule_matches(&users_absent));
assert!(!config_rule_matches(&rule(&["core"])));
let mut no_team = rule(&[]);
no_team.merge_whitelist_teams = None;
assert!(!config_rule_matches(&no_team));
let mut approvals_off = rule(&[]);
approvals_off.enable_approvals_whitelist = Some(false);
assert!(!config_rule_matches(&approvals_off));
}