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

Commit 41daa67

Browse files
KobzolMark-Simulacrum
authored andcommitted
Download information about organization app installations
1 parent 4f0c8a6 commit 41daa67

File tree

3 files changed

+115
-4
lines changed

3 files changed

+115
-4
lines changed

src/github/api/mod.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ impl HttpClient {
113113

114114
fn rest_paginated<F, T>(&self, method: &Method, url: String, mut f: F) -> anyhow::Result<()>
115115
where
116-
F: FnMut(Vec<T>) -> anyhow::Result<()>,
116+
F: FnMut(T) -> anyhow::Result<()>,
117117
T: DeserializeOwned,
118118
{
119119
let mut next = Some(url);
@@ -248,10 +248,24 @@ impl fmt::Display for RepoPermission {
248248
}
249249
}
250250

251+
#[derive(serde::Deserialize, Debug)]
252+
pub(crate) struct OrgAppInstallation {
253+
#[serde(rename = "id")]
254+
pub(crate) installation_id: u64,
255+
pub(crate) app_id: u64,
256+
}
257+
258+
#[derive(serde::Deserialize, Debug)]
259+
pub(crate) struct RepoAppInstallation {
260+
pub(crate) name: String,
261+
}
262+
251263
#[derive(serde::Deserialize, Debug)]
252264
pub(crate) struct Repo {
253265
#[serde(rename = "node_id")]
254266
pub(crate) id: String,
267+
#[serde(rename = "id")]
268+
pub(crate) repo_id: u64,
255269
pub(crate) name: String,
256270
#[serde(alias = "owner", deserialize_with = "repo_owner")]
257271
pub(crate) org: String,

src/github/api/read.rs

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::github::api::{
22
team_node_id, user_node_id, BranchProtection, GraphNode, GraphNodes, GraphPageInfo, HttpClient,
3-
Login, Repo, RepoTeam, RepoUser, Team, TeamMember, TeamRole,
3+
Login, OrgAppInstallation, Repo, RepoAppInstallation, RepoTeam, RepoUser, Team, TeamMember,
4+
TeamRole,
45
};
56
use reqwest::Method;
67
use std::collections::{HashMap, HashSet};
@@ -12,6 +13,15 @@ pub(crate) trait GithubRead {
1213
/// Get the owners of an org
1314
fn org_owners(&self, org: &str) -> anyhow::Result<HashSet<u64>>;
1415

16+
/// Get the app installations of an org
17+
fn org_app_installations(&self, org: &str) -> anyhow::Result<Vec<OrgAppInstallation>>;
18+
19+
/// Get the repositories enabled for an app installation.
20+
fn app_installation_repos(
21+
&self,
22+
installation_id: u64,
23+
) -> anyhow::Result<Vec<RepoAppInstallation>>;
24+
1525
/// Get all teams associated with a org
1626
///
1727
/// Returns a list of tuples of team name and slug
@@ -110,6 +120,45 @@ impl GithubRead for GitHubApiRead {
110120
Ok(owners)
111121
}
112122

123+
fn org_app_installations(&self, org: &str) -> anyhow::Result<Vec<OrgAppInstallation>> {
124+
#[derive(serde::Deserialize, Debug)]
125+
struct InstallationPage {
126+
installations: Vec<OrgAppInstallation>,
127+
}
128+
129+
let mut installations = Vec::new();
130+
self.client.rest_paginated(
131+
&Method::GET,
132+
format!("orgs/{org}/installations"),
133+
|response: InstallationPage| {
134+
installations.extend(response.installations);
135+
Ok(())
136+
},
137+
)?;
138+
Ok(installations)
139+
}
140+
141+
fn app_installation_repos(
142+
&self,
143+
installation_id: u64,
144+
) -> anyhow::Result<Vec<RepoAppInstallation>> {
145+
#[derive(serde::Deserialize, Debug)]
146+
struct InstallationPage {
147+
repositories: Vec<RepoAppInstallation>,
148+
}
149+
150+
let mut installations = Vec::new();
151+
self.client.rest_paginated(
152+
&Method::GET,
153+
format!("user/installations/{installation_id}/repositories"),
154+
|response: InstallationPage| {
155+
installations.extend(response.repositories);
156+
Ok(())
157+
},
158+
)?;
159+
Ok(installations)
160+
}
161+
113162
fn org_teams(&self, org: &str) -> anyhow::Result<Vec<(String, String)>> {
114163
let mut teams = Vec::new();
115164

src/github/mod.rs

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,37 @@ pub(crate) fn create_diff(
2323
github.diff_all()
2424
}
2525

26+
type OrgName = String;
27+
type RepoName = String;
28+
29+
#[derive(Clone, Debug)]
30+
enum GithubApp {
31+
RenovateBot,
32+
}
33+
34+
impl GithubApp {
35+
fn from_id(app_id: u64) -> Option<Self> {
36+
match app_id {
37+
2740 => Some(GithubApp::RenovateBot),
38+
_ => None,
39+
}
40+
}
41+
}
42+
43+
#[derive(Clone, Debug)]
44+
struct GithubAppInstallation {
45+
app: GithubApp,
46+
installation_id: u64,
47+
repositories: HashSet<RepoName>,
48+
}
49+
2650
struct SyncGitHub {
2751
github: Box<dyn GithubRead>,
2852
teams: Vec<rust_team_data::v1::Team>,
2953
repos: Vec<rust_team_data::v1::Repo>,
3054
usernames_cache: HashMap<u64, String>,
31-
org_owners: HashMap<String, HashSet<u64>>,
55+
org_owners: HashMap<OrgName, HashSet<u64>>,
56+
org_apps: HashMap<OrgName, Vec<GithubAppInstallation>>,
3257
}
3358

3459
impl SyncGitHub {
@@ -50,15 +75,37 @@ impl SyncGitHub {
5075
let usernames_cache = github.usernames(&users)?;
5176

5277
debug!("caching organization owners");
53-
let orgs = teams
78+
let mut orgs = teams
5479
.iter()
5580
.filter_map(|t| t.github.as_ref())
5681
.flat_map(|gh| &gh.teams)
5782
.map(|gh_team| &gh_team.org)
5883
.collect::<HashSet<_>>();
84+
5985
let mut org_owners = HashMap::new();
86+
let mut org_apps = HashMap::new();
87+
6088
for org in &orgs {
6189
org_owners.insert((*org).to_string(), github.org_owners(org)?);
90+
91+
let mut installations: Vec<GithubAppInstallation> = vec![];
92+
93+
for installation in github.org_app_installations(org)? {
94+
if let Some(app) = GithubApp::from_id(installation.app_id) {
95+
let mut repositories = HashSet::new();
96+
for repo_installation in
97+
github.app_installation_repos(installation.installation_id)?
98+
{
99+
repositories.insert(repo_installation.name);
100+
}
101+
installations.push(GithubAppInstallation {
102+
app,
103+
installation_id: installation.installation_id,
104+
repositories,
105+
});
106+
}
107+
}
108+
org_apps.insert(org.to_string(), installations);
62109
}
63110

64111
Ok(SyncGitHub {
@@ -67,6 +114,7 @@ impl SyncGitHub {
67114
repos,
68115
usernames_cache,
69116
org_owners,
117+
org_apps,
70118
})
71119
}
72120

0 commit comments

Comments
 (0)