Skip to content

Commit c0a83ce

Browse files
committed
Create TeamApiClient and route all team data requests through it
1 parent 86cc36d commit c0a83ce

File tree

18 files changed

+172
-110
lines changed

18 files changed

+172
-110
lines changed

src/actions.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use serde::{Deserialize, Serialize};
77
use tera::{Context, Tera};
88

99
use crate::github::{self, GithubClient, Repository};
10+
use crate::team_data::TeamApiClient;
1011

1112
#[async_trait]
1213
pub trait Action {
@@ -106,6 +107,7 @@ impl<'a> Action for Step<'a> {
106107
async fn call(&self) -> anyhow::Result<String> {
107108
let mut gh = GithubClient::new_from_env();
108109
gh.set_retry_rate_limit(true);
110+
let team_api = TeamApiClient::new_from_env();
109111

110112
let mut context = Context::new();
111113
let mut results = HashMap::new();
@@ -130,6 +132,7 @@ impl<'a> Action for Step<'a> {
130132
let kind = *kind;
131133
let repository = repository.clone();
132134
let gh = gh.clone();
135+
let team_api = team_api.clone();
133136
let query = query.clone();
134137
handles.push(tokio::task::spawn(async move {
135138
let _permit = semaphore.acquire().await?;
@@ -148,6 +151,7 @@ impl<'a> Action for Step<'a> {
148151
mcps_groups.contains(&name.as_str())
149152
&& repository.full_name.contains("rust-lang/compiler-team"),
150153
&gh,
154+
&team_api,
151155
)
152156
.await?;
153157
Ok((name, kind, issues))

src/bin/project_goals.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use clap::Parser;
2+
use triagebot::team_data::TeamApiClient;
23
use triagebot::zulip::client::ZulipClient;
34
use triagebot::{github::GithubClient, handlers::project_goals};
45

@@ -24,9 +25,11 @@ async fn main() -> anyhow::Result<()> {
2425
let opt = Opt::parse();
2526
let gh = GithubClient::new_from_env();
2627
let zulip = ZulipClient::new_from_env();
28+
let team_api = TeamApiClient::new_from_env();
2729
project_goals::ping_project_goals_owners(
2830
&gh,
2931
&zulip,
32+
&team_api,
3033
opt.dry_run,
3134
opt.days_threshold,
3235
&opt.next_meeting_date,

src/github.rs

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::team_data::TeamApiClient;
12
use anyhow::{anyhow, Context};
23
use async_trait::async_trait;
34
use bytes::Bytes;
@@ -240,9 +241,9 @@ impl User {
240241
.await
241242
}
242243

243-
pub async fn is_team_member<'a>(&'a self, client: &'a GithubClient) -> anyhow::Result<bool> {
244+
pub async fn is_team_member<'a>(&'a self, client: &'a TeamApiClient) -> anyhow::Result<bool> {
244245
log::trace!("Getting team membership for {:?}", self.login);
245-
let permission = crate::team_data::teams(client).await?;
246+
let permission = client.teams().await?;
246247
let map = permission.teams;
247248
let is_triager = map
248249
.get("wg-triage")
@@ -268,10 +269,10 @@ impl User {
268269

269270
// Returns the ID of the given user, if the user is in the `all` team.
270271
pub async fn get_id_for_username(
271-
client: &GithubClient,
272+
client: &TeamApiClient,
272273
login: &str,
273274
) -> anyhow::Result<Option<u64>> {
274-
let permission = crate::team_data::teams(client).await?;
275+
let permission = client.teams().await?;
275276
let map = permission.teams;
276277
let login = login.to_lowercase();
277278
Ok(map["all"]
@@ -282,21 +283,21 @@ pub async fn get_id_for_username(
282283
}
283284

284285
pub async fn get_team(
285-
client: &GithubClient,
286+
client: &TeamApiClient,
286287
team: &str,
287288
) -> anyhow::Result<Option<rust_team_data::v1::Team>> {
288-
let permission = crate::team_data::teams(client).await?;
289+
let permission = client.teams().await?;
289290
let mut map = permission.teams;
290291
Ok(map.swap_remove(team))
291292
}
292293

293294
/// Fetches a Rust team via its GitHub team name.
294295
pub async fn get_team_by_github_name(
295-
client: &GithubClient,
296+
client: &TeamApiClient,
296297
org: &str,
297298
team: &str,
298299
) -> anyhow::Result<Option<rust_team_data::v1::Team>> {
299-
let teams = crate::team_data::teams(client).await?;
300+
let teams = client.teams().await?;
300301
for rust_team in teams.teams.into_values() {
301302
if let Some(github) = &rust_team.github {
302303
for gh_team in &github.teams {
@@ -2059,10 +2060,11 @@ impl<'q> IssuesQuery for Query<'q> {
20592060
repo: &'a Repository,
20602061
include_fcp_details: bool,
20612062
include_mcp_details: bool,
2062-
client: &'a GithubClient,
2063+
gh_client: &'a GithubClient,
2064+
team_api_client: &'a TeamApiClient,
20632065
) -> anyhow::Result<Vec<crate::actions::IssueDecorator>> {
20642066
let issues = repo
2065-
.get_issues(&client, self)
2067+
.get_issues(&gh_client, self)
20662068
.await
20672069
.with_context(|| "Unable to get issues.")?;
20682070

@@ -2075,7 +2077,7 @@ impl<'q> IssuesQuery for Query<'q> {
20752077
};
20762078

20772079
let zulip_map = if include_fcp_details {
2078-
Some(crate::team_data::zulip_map(client).await?)
2080+
Some(team_api_client.zulip_map().await?)
20792081
} else {
20802082
None
20812083
};
@@ -2111,7 +2113,7 @@ impl<'q> IssuesQuery for Query<'q> {
21112113
("".to_string(), "".to_string())
21122114
} else {
21132115
let comment = issue
2114-
.get_comment(&client, fk_initiating_comment.try_into()?)
2116+
.get_comment(&gh_client, fk_initiating_comment.try_into()?)
21152117
.await
21162118
.with_context(|| {
21172119
format!(
@@ -2176,7 +2178,7 @@ impl<'q> IssuesQuery for Query<'q> {
21762178
};
21772179

21782180
let mcp_details = if include_mcp_details {
2179-
let first100_comments = issue.get_first100_comments(&client).await?;
2181+
let first100_comments = issue.get_first100_comments(&gh_client).await?;
21802182
let (zulip_link, concerns) = if !first100_comments.is_empty() {
21812183
let split = re_zulip_link
21822184
.split(&first100_comments[0].body)
@@ -2891,7 +2893,8 @@ pub trait IssuesQuery {
28912893
repo: &'a Repository,
28922894
include_fcp_details: bool,
28932895
include_mcp_details: bool,
2894-
client: &'a GithubClient,
2896+
gh_client: &'a GithubClient,
2897+
team_api_client: &'a TeamApiClient,
28952898
) -> anyhow::Result<Vec<crate::actions::IssueDecorator>>;
28962899
}
28972900

@@ -2904,6 +2907,7 @@ impl IssuesQuery for LeastRecentlyReviewedPullRequests {
29042907
_include_fcp_details: bool,
29052908
_include_mcp_details: bool,
29062909
client: &'a GithubClient,
2910+
_team_api_client: &'a TeamApiClient,
29072911
) -> anyhow::Result<Vec<crate::actions::IssueDecorator>> {
29082912
use cynic::QueryBuilder;
29092913
use github_graphql::queries;
@@ -3122,6 +3126,7 @@ impl IssuesQuery for DesignMeetings {
31223126
_include_fcp_details: bool,
31233127
_include_mcp_details: bool,
31243128
client: &'a GithubClient,
3129+
_team_api_client: &'a TeamApiClient,
31253130
) -> anyhow::Result<Vec<crate::actions::IssueDecorator>> {
31263131
use github_graphql::project_items::ProjectV2ItemContent;
31273132

src/handlers.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::config::{self, Config, ConfigurationError};
22
use crate::github::{Event, GithubClient, IssueCommentAction, IssuesAction, IssuesEvent};
33
use crate::handlers::pr_tracking::ReviewerWorkqueue;
4+
use crate::team_data::TeamApiClient;
45
use crate::zulip::client::ZulipClient;
56
use octocrab::Octocrab;
67
use parser::command::{assign::AssignCommand, Command, Input};
@@ -374,6 +375,7 @@ command_handlers! {
374375
pub struct Context {
375376
pub github: GithubClient,
376377
pub zulip: ZulipClient,
378+
pub team_api: TeamApiClient,
377379
pub db: crate::db::ClientPool,
378380
pub username: String,
379381
pub octocrab: Octocrab,

src/handlers/assign.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -388,7 +388,7 @@ async fn determine_assignee(
388388
diff: &[FileDiff],
389389
) -> anyhow::Result<(Option<ReviewerSelection>, bool)> {
390390
let mut db_client = ctx.db.get().await;
391-
let teams = crate::team_data::teams(&ctx.github).await?;
391+
let teams = &ctx.team_api.teams().await?;
392392
if let Some(name) = assign_command {
393393
// User included `r?` in the opening PR body.
394394
match find_reviewer_from_names(
@@ -564,12 +564,12 @@ pub(super) async fn handle_command(
564564
event: &Event,
565565
cmd: AssignCommand,
566566
) -> anyhow::Result<()> {
567-
let is_team_member = if let Err(_) | Ok(false) = event.user().is_team_member(&ctx.github).await
568-
{
569-
false
570-
} else {
571-
true
572-
};
567+
let is_team_member =
568+
if let Err(_) | Ok(false) = event.user().is_team_member(&ctx.team_api).await {
569+
false
570+
} else {
571+
true
572+
};
573573

574574
// Don't handle commands in comments from the bot. Some of the comments it
575575
// posts contain commands to instruct the user, not things that the bot
@@ -599,7 +599,7 @@ pub(super) async fn handle_command(
599599
return Ok(());
600600
}
601601

602-
let teams = crate::team_data::teams(&ctx.github).await?;
602+
let teams = ctx.team_api.teams().await?;
603603

604604
let assignee = match cmd {
605605
AssignCommand::Claim => event.user().login.clone(),

src/handlers/close.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ pub(super) async fn handle_command(
1212
let issue = event.issue().unwrap();
1313
let is_team_member = event
1414
.user()
15-
.is_team_member(&ctx.github)
15+
.is_team_member(&ctx.team_api)
1616
.await
1717
.unwrap_or(false);
1818
if !is_team_member {

src/handlers/major_change.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ pub(super) async fn handle_command(
247247

248248
let is_team_member = event
249249
.user()
250-
.is_team_member(&ctx.github)
250+
.is_team_member(&ctx.team_api)
251251
.await
252252
.ok()
253253
.unwrap_or(false);

src/handlers/nominate.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,12 @@ pub(super) async fn handle_command(
1414
event: &Event,
1515
cmd: NominateCommand,
1616
) -> anyhow::Result<()> {
17-
let is_team_member = if let Err(_) | Ok(false) = event.user().is_team_member(&ctx.github).await
18-
{
19-
false
20-
} else {
21-
true
22-
};
17+
let is_team_member =
18+
if let Err(_) | Ok(false) = event.user().is_team_member(&ctx.team_api).await {
19+
false
20+
} else {
21+
true
22+
};
2323

2424
if !is_team_member {
2525
let cmnt = ErrorComment::new(

src/handlers/notification.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ pub(super) async fn handle(ctx: &Context, event: &Event) -> anyhow::Result<()> {
6969
//
7070
// If the user intended to ping themselves, they can add the GitHub comment
7171
// via the Zulip interface.
72-
match get_id_for_username(&ctx.github, &event.user().login).await {
72+
match get_id_for_username(&ctx.team_api, &event.user().login).await {
7373
Ok(Some(id)) => {
7474
users_notified.insert(id.try_into().unwrap());
7575
}
@@ -136,7 +136,7 @@ async fn id_from_user(
136136
//
137137
// We may also want to be able to categorize into these buckets
138138
// *after* the ping occurs and is initially processed.
139-
let team = match github::get_team_by_github_name(&ctx.github, org, team).await {
139+
let team = match github::get_team_by_github_name(&ctx.team_api, org, team).await {
140140
Ok(Some(team)) => team,
141141
Ok(None) => {
142142
// If the team is in rust-lang*, then this is probably an error (potentially user
@@ -170,7 +170,7 @@ async fn id_from_user(
170170
Some(team.name),
171171
)))
172172
} else {
173-
let id = get_id_for_username(&ctx.github, login)
173+
let id = get_id_for_username(&ctx.team_api, login)
174174
.await
175175
.with_context(|| format!("failed to get user {} ID", login))?;
176176
let Some(id) = id else {

src/handlers/ping.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@ pub(super) async fn handle_command(
1818
event: &Event,
1919
team_name: PingCommand,
2020
) -> anyhow::Result<()> {
21-
let is_team_member = if let Err(_) | Ok(false) = event.user().is_team_member(&ctx.github).await
22-
{
23-
false
24-
} else {
25-
true
26-
};
21+
let is_team_member =
22+
if let Err(_) | Ok(false) = event.user().is_team_member(&ctx.team_api).await {
23+
false
24+
} else {
25+
true
26+
};
2727

2828
if !is_team_member {
2929
let cmnt = ErrorComment::new(
@@ -49,7 +49,7 @@ pub(super) async fn handle_command(
4949
return Ok(());
5050
}
5151
};
52-
let team = github::get_team(&ctx.github, &gh_team).await?;
52+
let team = github::get_team(&ctx.team_api, &gh_team).await?;
5353
let team = match team {
5454
Some(team) => team,
5555
None => {

0 commit comments

Comments
 (0)