Skip to content

Commit ac98f09

Browse files
committed
refactor: address review comments
1 parent 632fb4e commit ac98f09

File tree

3 files changed

+59
-63
lines changed

3 files changed

+59
-63
lines changed

src/schema.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ pub(crate) use crate::permissions::Permissions;
33
use anyhow::{bail, format_err, Error};
44
use serde::de::{Deserialize, Deserializer};
55
use serde_untagged::UntaggedEnumVisitor;
6-
use std::collections::{BTreeSet, HashMap, HashSet};
6+
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
77

88
#[derive(serde_derive::Deserialize, Debug)]
99
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
@@ -814,7 +814,7 @@ pub(crate) struct Repo {
814814
#[serde(default)]
815815
pub crates_io_publishing: Vec<CratesIoPublishing>,
816816
#[serde(default)]
817-
pub environments: HashMap<String, Environment>,
817+
pub environments: BTreeMap<String, Environment>,
818818
}
819819

820820
#[derive(serde_derive::Deserialize, Debug, Clone, PartialEq)]

sync-team/src/github/api/read.rs

Lines changed: 44 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -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
}

sync-team/src/github/api/write.rs

Lines changed: 13 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -513,30 +513,7 @@ impl GitHubWrite {
513513
"Creating environment '{name}' in '{org}/{repo}' with branches: {:?}",
514514
branches
515515
);
516-
if !self.dry_run {
517-
// REST API: PUT /repos/{owner}/{repo}/environments/{environment_name}
518-
// https://docs.github.com/en/rest/deployments/environments#create-or-update-an-environment
519-
let url = GitHubUrl::repos(org, repo, &format!("environments/{}", name))?;
520-
521-
let body = if branches.is_empty() {
522-
serde_json::json!({})
523-
} else {
524-
serde_json::json!({
525-
"deployment_branch_policy": {
526-
"protected_branches": false,
527-
"custom_branch_policies": true
528-
}
529-
})
530-
};
531-
532-
self.client.send(Method::PUT, &url, &body)?;
533-
534-
// If we have custom branches, we need to set them via a separate API call
535-
if !branches.is_empty() {
536-
self.set_environment_branch_policies(org, repo, name, branches)?;
537-
}
538-
}
539-
Ok(())
516+
self.upsert_environment(org, repo, name, branches)
540517
}
541518

542519
/// Update an environment in a repository
@@ -551,6 +528,17 @@ impl GitHubWrite {
551528
"Updating environment '{name}' in '{org}/{repo}' with branches: {:?}",
552529
branches
553530
);
531+
self.upsert_environment(org, repo, name, branches)
532+
}
533+
534+
/// Internal helper to create or update an environment
535+
fn upsert_environment(
536+
&self,
537+
org: &str,
538+
repo: &str,
539+
name: &str,
540+
branches: &[String],
541+
) -> anyhow::Result<()> {
554542
if !self.dry_run {
555543
// REST API: PUT /repos/{owner}/{repo}/environments/{environment_name}
556544
// https://docs.github.com/en/rest/deployments/environments#create-or-update-an-environment
@@ -571,7 +559,7 @@ impl GitHubWrite {
571559

572560
self.client.send(Method::PUT, &url, &body)?;
573561

574-
// This ensures old policies are cleaned up when transitioning to unrestricted deployments
562+
// Always sync branch policies to ensure cleanup of old policies
575563
self.set_environment_branch_policies(org, repo, name, branches)?;
576564
}
577565
Ok(())

0 commit comments

Comments
 (0)