@@ -390,10 +390,8 @@ impl SyncGitHub {
390390
391391 let permission_diffs = self . diff_permissions ( expected_repo) ?;
392392
393- // Always diff branch protections
394393 let branch_protection_diffs = self . diff_branch_protections ( & actual_repo, expected_repo) ?;
395394
396- // Additionally diff rulesets if configured
397395 let ruleset_diffs = if self . should_use_rulesets ( expected_repo) {
398396 self . diff_rulesets ( expected_repo) ?
399397 } else {
@@ -520,12 +518,12 @@ impl SyncGitHub {
520518 ) -> anyhow:: Result < Vec < EnvironmentDiff > > {
521519 let mut environment_diffs = Vec :: new ( ) ;
522520
523- let actual_environments : HashSet < String > = self
521+ let actual_environments_map = self
524522 . github
525- . repo_environments ( & expected_repo. org , & expected_repo. name ) ?
526- . into_keys ( )
527- . collect ( ) ;
523+ . repo_environments ( & expected_repo. org , & expected_repo. name ) ?;
528524
525+ let actual_environments: HashSet < String > =
526+ actual_environments_map. keys ( ) . cloned ( ) . collect ( ) ;
529527 let expected_environments: HashSet < String > =
530528 expected_repo. environments . keys ( ) . cloned ( ) . collect ( ) ;
531529
@@ -540,6 +538,68 @@ impl SyncGitHub {
540538 environment_diffs. push ( EnvironmentDiff :: Create ( env_name, env. clone ( ) ) ) ;
541539 }
542540
541+ // Environments to update (sorted for deterministic output)
542+ let mut to_update: Vec < _ > = expected_environments
543+ . intersection ( & actual_environments)
544+ . cloned ( )
545+ . collect ( ) ;
546+ to_update. sort ( ) ;
547+ for env_name in to_update {
548+ let expected_env = expected_repo. environments . get ( & env_name) . unwrap ( ) ;
549+ let actual_env = actual_environments_map. get ( & env_name) . unwrap ( ) ;
550+
551+ let expected_branches: HashSet < _ > = expected_env. branches . iter ( ) . collect ( ) ;
552+ let actual_branches: HashSet < _ > = actual_env. branches . iter ( ) . collect ( ) ;
553+
554+ let expected_tags: HashSet < _ > = expected_env. tags . iter ( ) . collect ( ) ;
555+ let actual_tags: HashSet < _ > = actual_env. tags . iter ( ) . collect ( ) ;
556+
557+ let mut add_branches: Vec < _ > = expected_branches
558+ . difference ( & actual_branches)
559+ . map ( |s| s. to_string ( ) )
560+ . collect ( ) ;
561+ add_branches. sort ( ) ;
562+
563+ let mut remove_branches: Vec < _ > = actual_branches
564+ . difference ( & expected_branches)
565+ . map ( |s| s. to_string ( ) )
566+ . collect ( ) ;
567+ remove_branches. sort ( ) ;
568+
569+ let mut add_tags: Vec < _ > = expected_tags
570+ . difference ( & actual_tags)
571+ . map ( |s| s. to_string ( ) )
572+ . collect ( ) ;
573+ add_tags. sort ( ) ;
574+
575+ let mut remove_tags: Vec < _ > = actual_tags
576+ . difference ( & expected_tags)
577+ . map ( |s| s. to_string ( ) )
578+ . collect ( ) ;
579+ remove_tags. sort ( ) ;
580+
581+ if !add_branches. is_empty ( )
582+ || !remove_branches. is_empty ( )
583+ || !add_tags. is_empty ( )
584+ || !remove_tags. is_empty ( )
585+ {
586+ let mut new_branches = expected_env. branches . clone ( ) ;
587+ new_branches. sort ( ) ;
588+ let mut new_tags = expected_env. tags . clone ( ) ;
589+ new_tags. sort ( ) ;
590+
591+ environment_diffs. push ( EnvironmentDiff :: Update {
592+ name : env_name,
593+ add_branches,
594+ remove_branches,
595+ add_tags,
596+ remove_tags,
597+ new_branches,
598+ new_tags,
599+ } ) ;
600+ }
601+ }
602+
543603 // Environments to delete (sorted for deterministic output)
544604 let mut to_delete: Vec < _ > = actual_environments
545605 . difference ( & expected_environments)
@@ -1161,6 +1221,15 @@ struct UpdateRepoDiff {
11611221#[ derive( Debug ) ]
11621222enum EnvironmentDiff {
11631223 Create ( String , rust_team_data:: v1:: Environment ) ,
1224+ Update {
1225+ name : String ,
1226+ add_branches : Vec < String > ,
1227+ remove_branches : Vec < String > ,
1228+ add_tags : Vec < String > ,
1229+ remove_tags : Vec < String > ,
1230+ new_branches : Vec < String > ,
1231+ new_tags : Vec < String > ,
1232+ } ,
11641233 Delete ( String ) ,
11651234}
11661235
@@ -1230,6 +1299,14 @@ impl UpdateRepoDiff {
12301299 EnvironmentDiff :: Create ( name, env) => {
12311300 sync. create_environment ( & self . org , & self . name , name, & env. branches , & env. tags ) ?;
12321301 }
1302+ EnvironmentDiff :: Update {
1303+ name,
1304+ new_branches,
1305+ new_tags,
1306+ ..
1307+ } => {
1308+ sync. update_environment ( & self . org , & self . name , name, new_branches, new_tags) ?;
1309+ }
12331310 EnvironmentDiff :: Delete ( name) => {
12341311 sync. delete_environment ( & self . org , & self . name , name) ?;
12351312 }
@@ -1325,6 +1402,40 @@ impl std::fmt::Display for UpdateRepoDiff {
13251402 writeln ! ( f, " Tags: {}" , env. tags. join( ", " ) ) ?;
13261403 }
13271404 }
1405+ EnvironmentDiff :: Update {
1406+ name,
1407+ add_branches,
1408+ remove_branches,
1409+ add_tags,
1410+ remove_tags,
1411+ new_branches : _,
1412+ new_tags : _,
1413+ } => {
1414+ writeln ! ( f, " 🔄 Update: {name}" ) ?;
1415+ if !add_branches. is_empty ( ) {
1416+ writeln ! ( f, " Adding branches: {}" , add_branches. join( ", " ) ) ?;
1417+ }
1418+ if !remove_branches. is_empty ( ) {
1419+ writeln ! (
1420+ f,
1421+ " Removing branches: {}" ,
1422+ remove_branches. join( ", " )
1423+ ) ?;
1424+ }
1425+ if !add_tags. is_empty ( ) {
1426+ writeln ! ( f, " Adding tags: {}" , add_tags. join( ", " ) ) ?;
1427+ }
1428+ if !remove_tags. is_empty ( ) {
1429+ writeln ! ( f, " Removing tags: {}" , remove_tags. join( ", " ) ) ?;
1430+ }
1431+ if add_branches. is_empty ( )
1432+ && remove_branches. is_empty ( )
1433+ && add_tags. is_empty ( )
1434+ && remove_tags. is_empty ( )
1435+ {
1436+ writeln ! ( f, " No pattern changes" ) ?;
1437+ }
1438+ }
13281439 EnvironmentDiff :: Delete ( name) => writeln ! ( f, " ❌ Delete: {name}" ) ?,
13291440 }
13301441 }
0 commit comments