@@ -450,9 +450,16 @@ impl GithubRead for GitHubApiRead {
450450 org : & str ,
451451 repo : & str ,
452452 ) -> anyhow:: Result < HashMap < String , Environment > > {
453+ #[ derive( serde:: Deserialize ) ]
454+ struct ProtectionRule {
455+ #[ serde( rename = "type" ) ]
456+ rule_type : String ,
457+ }
458+
453459 #[ derive( serde:: Deserialize ) ]
454460 struct GitHubEnvironment {
455461 name : String ,
462+ protection_rules : Vec < ProtectionRule > ,
456463 }
457464
458465 #[ derive( serde:: Deserialize ) ]
@@ -470,50 +477,51 @@ impl GithubRead for GitHubApiRead {
470477 branch_policies : Vec < BranchPolicy > ,
471478 }
472479
473- let mut environment_names = Vec :: new ( ) ;
480+ let mut env_infos = Vec :: new ( ) ;
474481
475- // First, fetch all environment names
476- // REST API endpoint for environments
477- // https://docs.github.com/en/rest/deployments/environments#list-environments
482+ // Fetch all environments with their protection_rules metadata
483+ // REST API: https://docs.github.com/en/rest/deployments/environments#list-environments
478484 self . client . rest_paginated (
479485 & Method :: GET ,
480486 & GitHubUrl :: repos ( org, repo, "environments" ) ?,
481487 |resp : EnvironmentsResponse | {
482- environment_names . extend ( resp. environments . into_iter ( ) . map ( |e| e . name ) ) ;
488+ env_infos . extend ( resp. environments ) ;
483489 Ok ( ( ) )
484490 } ,
485491 ) ?;
486492
487- let mut environments: HashMap < String , Environment > = HashMap :: new ( ) ;
488-
489- // Then, for each environment, fetch its deployment branch policies
490- // https://docs.github.com/en/rest/deployments/branch-policies#list-deployment-branch-policies
491- for env_name in environment_names {
492- let mut branches = Vec :: new ( ) ;
493-
494- // Fetch branch policies for this environment
495- let result = self . client . rest_paginated (
496- & Method :: GET ,
497- & GitHubUrl :: repos (
498- org,
499- repo,
500- & format ! ( "environments/{}/deployment-branch-policies" , env_name) ,
501- ) ?,
502- |resp : BranchPoliciesResponse | {
503- branches. extend ( resp. branch_policies . into_iter ( ) . map ( |p| p. name ) ) ;
504- Ok ( ( ) )
505- } ,
506- ) ;
507-
508- // If the API call fails (e.g., 404 when no policies are configured),
509- // treat it as an empty branches list
510- if result. is_err ( ) {
511- branches. clear ( ) ;
512- }
513-
514- environments. insert ( env_name, Environment { branches } ) ;
515- }
516-
517- Ok ( environments)
493+ // For each environment, fetch deployment branch policies if they exist
494+ // REST API: https://docs.github.com/en/rest/deployments/branch-policies#list-deployment-branch-policies
495+ env_infos
496+ . into_iter ( )
497+ . map ( |env_info| {
498+ // Check if branch policies exist by looking at protection_rules metadata
499+ let has_branch_policies = env_info
500+ . protection_rules
501+ . iter ( )
502+ . any ( |rule| rule. rule_type == "branch_policy" ) ;
503+
504+ let branches = if has_branch_policies {
505+ let mut branches = Vec :: new ( ) ;
506+ self . client . rest_paginated (
507+ & Method :: GET ,
508+ & GitHubUrl :: repos (
509+ org,
510+ repo,
511+ & format ! ( "environments/{}/deployment-branch-policies" , env_info. name) ,
512+ ) ?,
513+ |resp : BranchPoliciesResponse | {
514+ branches. extend ( resp. branch_policies . into_iter ( ) . map ( |p| p. name ) ) ;
515+ Ok ( ( ) )
516+ } ,
517+ ) ?;
518+ branches
519+ } else {
520+ Vec :: new ( )
521+ } ;
522+
523+ Ok ( ( env_info. name , Environment { branches } ) )
524+ } )
525+ . collect ( )
518526 }
519527}
0 commit comments