@@ -9,6 +9,7 @@ use crate::sync::Config;
99use crate :: sync:: github:: api:: {
1010 GithubRead , Login , PushAllowanceActor , RepoPermission , RepoSettings , Ruleset ,
1111} ;
12+ use anyhow:: Context as _;
1213use futures_util:: StreamExt ;
1314use log:: debug;
1415use rust_team_data:: v1:: { Bot , BranchProtectionMode , MergeBot , ProtectionTarget } ;
@@ -370,6 +371,78 @@ impl SyncGitHub {
370371 self . config . enable_rulesets_repos . contains ( & repo_full_name)
371372 }
372373
374+ async fn construct_ruleset (
375+ & self ,
376+ expected_repo : & rust_team_data:: v1:: Repo ,
377+ branch_protection : & rust_team_data:: v1:: BranchProtection ,
378+ ) -> anyhow:: Result < api:: Ruleset > {
379+ let bypass_actors = self . bypass_actors ( expected_repo, branch_protection) . await ?;
380+
381+ Ok ( construct_ruleset ( branch_protection, bypass_actors) )
382+ }
383+
384+ async fn bypass_actors (
385+ & self ,
386+ expected_repo : & rust_team_data:: v1:: Repo ,
387+ branch_protection : & rust_team_data:: v1:: BranchProtection ,
388+ ) -> Result < Vec < api:: RulesetBypassActor > , anyhow:: Error > {
389+ use api:: { RulesetActorType , RulesetBypassActor , RulesetBypassMode } ;
390+
391+ let mut bypass_actors = Vec :: new ( ) ;
392+ let allowed_teams = self
393+ . allowed_merge_teams ( expected_repo, branch_protection)
394+ . await ?;
395+ bypass_actors. extend ( allowed_teams) ;
396+ let allowed_apps = branch_protection
397+ . allowed_merge_apps
398+ . iter ( )
399+ . filter_map ( |app| {
400+ app. app_id ( ) . map ( |app_id| RulesetBypassActor {
401+ actor_id : app_id,
402+ actor_type : RulesetActorType :: Integration ,
403+ bypass_mode : RulesetBypassMode :: Always ,
404+ } )
405+ } ) ;
406+ bypass_actors. extend ( allowed_apps) ;
407+ Ok ( bypass_actors)
408+ }
409+
410+ async fn allowed_merge_teams (
411+ & self ,
412+ expected_repo : & rust_team_data:: v1:: Repo ,
413+ branch_protection : & rust_team_data:: v1:: BranchProtection ,
414+ ) -> Result < Vec < api:: RulesetBypassActor > , anyhow:: Error > {
415+ use api:: { RulesetActorType , RulesetBypassActor , RulesetBypassMode } ;
416+
417+ let mut allowed = vec ! [ ] ;
418+
419+ for team_name in & branch_protection. allowed_merge_teams {
420+ let github_team = self
421+ . github
422+ . team ( & expected_repo. org , team_name)
423+ . await ?
424+ . with_context ( || {
425+ format ! (
426+ "failed to find GitHub team '{team_name}' in org '{}' for repo '{}/{}'" ,
427+ expected_repo. org, expected_repo. org, expected_repo. name
428+ )
429+ } ) ?;
430+ let team_id = github_team. id . with_context ( || {
431+ format ! (
432+ "GitHub team '{team_name}' in org '{}' is missing an ID" ,
433+ expected_repo. org
434+ )
435+ } ) ?;
436+
437+ allowed. push ( RulesetBypassActor {
438+ actor_id : team_id as i64 ,
439+ actor_type : RulesetActorType :: Team ,
440+ bypass_mode : RulesetBypassMode :: Always ,
441+ } ) ;
442+ }
443+ Ok ( allowed)
444+ }
445+
373446 async fn diff_repo (
374447 & self ,
375448 expected_repo : & rust_team_data:: v1:: Repo ,
@@ -404,7 +477,9 @@ impl SyncGitHub {
404477 let use_rulesets = self . should_use_rulesets ( expected_repo) ;
405478 if use_rulesets {
406479 for branch_protection in & expected_repo. branch_protections {
407- let ruleset = construct_ruleset ( branch_protection) ;
480+ let ruleset = self
481+ . construct_ruleset ( expected_repo, branch_protection)
482+ . await ?;
408483 rulesets. push ( ruleset) ;
409484 }
410485 }
@@ -697,7 +772,9 @@ impl SyncGitHub {
697772
698773 // Process each branch protection as a potential ruleset
699774 for branch_protection in & expected_repo. branch_protections {
700- let expected_ruleset = construct_ruleset ( branch_protection) ;
775+ let expected_ruleset = self
776+ . construct_ruleset ( expected_repo, branch_protection)
777+ . await ?;
701778
702779 if let Some ( actual_ruleset) = rulesets_by_name. remove ( & expected_ruleset. name ) {
703780 let Ruleset {
@@ -1015,7 +1092,10 @@ fn github_int(value: u32) -> i32 {
10151092 i32:: try_from ( value) . unwrap_or_else ( |_| panic ! ( "Value {value} exceeds GitHub's Int range" ) )
10161093}
10171094
1018- pub fn construct_ruleset ( branch_protection : & rust_team_data:: v1:: BranchProtection ) -> api:: Ruleset {
1095+ pub fn construct_ruleset (
1096+ branch_protection : & rust_team_data:: v1:: BranchProtection ,
1097+ bypass_actors : Vec < api:: RulesetBypassActor > ,
1098+ ) -> api:: Ruleset {
10191099 use api:: * ;
10201100
10211101 let branch_protection_mode = get_branch_protection_mode ( branch_protection) ;
@@ -1102,19 +1182,6 @@ pub fn construct_ruleset(branch_protection: &rust_team_data::v1::BranchProtectio
11021182 rules. insert ( RulesetRule :: MergeQueue { parameters } ) ;
11031183 }
11041184
1105- // Build bypass actors from allowed merge apps
1106- let bypass_actors: Vec < RulesetBypassActor > = branch_protection
1107- . allowed_merge_apps
1108- . iter ( )
1109- . filter_map ( |app| {
1110- app. app_id ( ) . map ( |app_id| RulesetBypassActor {
1111- actor_id : app_id,
1112- actor_type : RulesetActorType :: Integration ,
1113- bypass_mode : RulesetBypassMode :: Always ,
1114- } )
1115- } )
1116- . collect ( ) ;
1117-
11181185 api:: Ruleset {
11191186 id : None ,
11201187 name : branch_protection
0 commit comments