Skip to content
This repository was archived by the owner on Mar 31, 2025. It is now read-only.

Commit 93ce0b3

Browse files
KobzolMark-Simulacrum
authored andcommitted
Add removal of repositories from installations
1 parent e8cd433 commit 93ce0b3

File tree

2 files changed

+66
-12
lines changed

2 files changed

+66
-12
lines changed

src/github/api/write.rs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -279,14 +279,33 @@ impl GitHubWrite {
279279
installation_id: u64,
280280
repository_id: u64,
281281
) -> anyhow::Result<()> {
282-
debug!("Adding installation {installation_id} to repository {repository_id}");
282+
debug!("Adding repository {repository_id} to installation {installation_id}");
283283
if !self.dry_run {
284284
self.client
285285
.req(
286286
Method::PUT,
287287
&format!("user/installations/{installation_id}/repositories/{repository_id}"),
288288
)?
289-
.send()?;
289+
.send()?
290+
.custom_error_for_status()?;
291+
}
292+
Ok(())
293+
}
294+
295+
pub(crate) fn remove_repo_from_app_installation(
296+
&self,
297+
installation_id: u64,
298+
repository_id: u64,
299+
) -> anyhow::Result<()> {
300+
debug!("Removing repository {repository_id} from installation {installation_id}");
301+
if !self.dry_run {
302+
self.client
303+
.req(
304+
Method::DELETE,
305+
&format!("user/installations/{installation_id}/repositories/{repository_id}"),
306+
)?
307+
.send()?
308+
.custom_error_for_status()?;
290309
}
291310
Ok(())
292311
}

src/github/mod.rs

Lines changed: 45 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@ mod api;
33
mod tests;
44

55
use self::api::{BranchProtectionOp, TeamPrivacy, TeamRole};
6-
use crate::github::api::{
7-
GithubRead, Login, PushAllowanceActor, Repo, RepoPermission, RepoSettings,
8-
};
6+
use crate::github::api::{GithubRead, Login, PushAllowanceActor, RepoPermission, RepoSettings};
97
use log::debug;
108
use rust_team_data::v1::Bot;
119
use std::collections::{HashMap, HashSet};
@@ -28,7 +26,7 @@ pub(crate) fn create_diff(
2826
type OrgName = String;
2927
type RepoName = String;
3028

31-
#[derive(Clone, Debug, PartialEq)]
29+
#[derive(Copy, Clone, Debug, PartialEq)]
3230
enum GithubApp {
3331
RenovateBot,
3432
}
@@ -91,7 +89,7 @@ impl SyncGitHub {
9189
let usernames_cache = github.usernames(&users)?;
9290

9391
debug!("caching organization owners");
94-
let mut orgs = teams
92+
let orgs = teams
9593
.iter()
9694
.filter_map(|t| t.github.as_ref())
9795
.flat_map(|gh| &gh.teams)
@@ -334,13 +332,39 @@ impl SyncGitHub {
334332
archived: expected_repo.archived,
335333
auto_merge_enabled: expected_repo.auto_merge_enabled,
336334
};
335+
336+
let existing_installations = self
337+
.org_apps
338+
.get(&expected_repo.org)
339+
.map(|installations| {
340+
installations
341+
.iter()
342+
.filter_map(|installation| {
343+
// Only load installations from apps that we know about, to avoid removing
344+
// unknown installations.
345+
if installation.repositories.contains(&actual_repo.name) {
346+
Some(AppInstallation {
347+
app: installation.app,
348+
installation_id: installation.installation_id,
349+
})
350+
} else {
351+
None
352+
}
353+
})
354+
.collect::<Vec<_>>()
355+
})
356+
.unwrap_or_default();
357+
let app_installation_diffs =
358+
self.diff_app_installations(expected_repo, &existing_installations)?;
337359
Ok(RepoDiff::Update(UpdateRepoDiff {
338360
org: expected_repo.org.clone(),
339361
name: actual_repo.name,
340362
repo_node_id: actual_repo.node_id,
363+
repo_id: actual_repo.repo_id,
341364
settings_diff: (old_settings, new_settings),
342365
permission_diffs,
343366
branch_protection_diffs,
367+
app_installation_diffs,
344368
}))
345369
}
346370

@@ -703,7 +727,7 @@ impl CreateRepoDiff {
703727
}
704728

705729
for installation in &self.app_installations {
706-
installation.apply(sync, &repo)?;
730+
installation.apply(sync, repo.repo_id)?;
707731
}
708732

709733
Ok(())
@@ -746,10 +770,12 @@ struct UpdateRepoDiff {
746770
org: String,
747771
name: String,
748772
repo_node_id: String,
773+
repo_id: u64,
749774
// old, new
750775
settings_diff: (RepoSettings, RepoSettings),
751776
permission_diffs: Vec<RepoPermissionAssignmentDiff>,
752777
branch_protection_diffs: Vec<BranchProtectionDiff>,
778+
app_installation_diffs: Vec<AppInstallationDiff>,
753779
}
754780

755781
impl UpdateRepoDiff {
@@ -761,6 +787,7 @@ impl UpdateRepoDiff {
761787
self.settings_diff.0 == self.settings_diff.1
762788
&& self.permission_diffs.is_empty()
763789
&& self.branch_protection_diffs.is_empty()
790+
&& self.app_installation_diffs.is_empty()
764791
}
765792

766793
fn can_be_modified(&self) -> bool {
@@ -788,6 +815,10 @@ impl UpdateRepoDiff {
788815
for branch_protection in &self.branch_protection_diffs {
789816
branch_protection.apply(sync, &self.org, &self.name, &self.repo_node_id)?;
790817
}
818+
819+
for app_installation in &self.app_installation_diffs {
820+
app_installation.apply(sync, self.repo_id)?;
821+
}
791822
Ok(())
792823
}
793824
}
@@ -841,6 +872,10 @@ impl std::fmt::Display for UpdateRepoDiff {
841872
for branch_protection_diff in &self.branch_protection_diffs {
842873
write!(f, "{branch_protection_diff}")?;
843874
}
875+
writeln!(f, " App installation changes:")?;
876+
for diff in &self.app_installation_diffs {
877+
write!(f, "{diff}")?;
878+
}
844879

845880
Ok(())
846881
}
@@ -1010,13 +1045,13 @@ enum AppInstallationDiff {
10101045
}
10111046

10121047
impl AppInstallationDiff {
1013-
fn apply(&self, sync: &GitHubWrite, repo: &Repo) -> anyhow::Result<()> {
1048+
fn apply(&self, sync: &GitHubWrite, repo_id: u64) -> anyhow::Result<()> {
10141049
match self {
10151050
AppInstallationDiff::Add(app) => {
1016-
sync.add_repo_to_app_installation(app.installation_id, repo.repo_id)?;
1051+
sync.add_repo_to_app_installation(app.installation_id, repo_id)?;
10171052
}
1018-
AppInstallationDiff::Remove(_) => {
1019-
todo!()
1053+
AppInstallationDiff::Remove(app) => {
1054+
sync.remove_repo_from_app_installation(app.installation_id, repo_id)?;
10201055
}
10211056
}
10221057
Ok(())

0 commit comments

Comments
 (0)