Skip to content

Commit 2c77a26

Browse files
committed
Add /gh-changes-since endpoint
1 parent bfc7964 commit 2c77a26

File tree

4 files changed

+99
-6
lines changed

4 files changed

+99
-6
lines changed

src/gh_changes_since.rs

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
use std::sync::Arc;
2+
3+
use anyhow::Context as _;
4+
use axum::{
5+
extract::{Path, State},
6+
response::{IntoResponse, Redirect, Response},
7+
};
8+
use hyper::StatusCode;
9+
10+
use crate::{github, handlers::Context, utils::AppError};
11+
12+
/// Redirects to either `/gh-range-diff` (when the base changed) or to GitHub's compare
13+
/// page (when the base is the same).
14+
///
15+
/// Takes an PR number and an `oldbase..oldhead` representing the range we are starting from.
16+
pub async fn gh_changes_since(
17+
Path((owner, repo, pr_num, oldbasehead)): Path<(String, String, u64, String)>,
18+
State(ctx): State<Arc<Context>>,
19+
) -> axum::response::Result<Response, AppError> {
20+
let Some((oldbase, oldhead)) = oldbasehead.split_once("..") else {
21+
return Ok((
22+
StatusCode::BAD_REQUEST,
23+
format!("`{oldbasehead}` is not in the form `base..head`"),
24+
)
25+
.into_response());
26+
};
27+
28+
let repos = ctx
29+
.team
30+
.repos()
31+
.await
32+
.context("unable to retrieve team repos")?;
33+
34+
// Verify that the request org is part of the Rust project
35+
let Some(repos) = repos.repos.get(&owner) else {
36+
return Ok((
37+
StatusCode::BAD_REQUEST,
38+
format!("organization `{owner}` is not part of the Rust Project team repos"),
39+
)
40+
.into_response());
41+
};
42+
43+
// Verify that the request repo is part of the Rust project
44+
if !repos.iter().any(|r| r.name == repo) {
45+
return Ok((
46+
StatusCode::BAD_REQUEST,
47+
format!("repository `{owner}` is not part of the Rust Project team repos"),
48+
)
49+
.into_response());
50+
}
51+
52+
let issue_repo = github::IssueRepository {
53+
organization: owner.to_string(),
54+
repository: repo.to_string(),
55+
};
56+
57+
let pr = ctx.github.pull_request(&issue_repo, pr_num).await?;
58+
59+
let newbase = &pr.base.as_ref().context("no base")?.sha;
60+
let newhead = &pr.head.as_ref().context("no head")?.sha;
61+
62+
// Has the base changed?
63+
if oldbase == newbase {
64+
// No, redirect to GitHub native compare page
65+
return Ok(Redirect::to(&format!(
66+
"https://github.com/{owner}/{repo}/compare/{oldhead}..{newhead}"
67+
))
68+
.into_response());
69+
}
70+
71+
// Yes, use our Github range-diff instead
72+
Ok(Redirect::to(&format!(
73+
"/gh-range-diff/{owner}/{repo}/{oldbase}..{oldhead}/{newbase}..{newhead}"
74+
))
75+
.into_response())
76+
}

src/github.rs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,16 @@ impl GithubClient {
270270
.await
271271
.context("failed to retrive the compare")
272272
}
273+
274+
pub async fn pull_request(&self, repo: &IssueRepository, pr_num: u64) -> anyhow::Result<Issue> {
275+
let url = format!("{}/pulls/{pr_num}", repo.url(&self));
276+
let mut pr: Issue = self
277+
.json(self.get(&url))
278+
.await
279+
.with_context(|| format!("{repo} failed to get pr {pr_num}"))?;
280+
pr.pull_request = Some(PullRequestDetails::new());
281+
Ok(pr)
282+
}
273283
}
274284

275285
#[derive(Debug, serde::Serialize)]
@@ -1982,13 +1992,15 @@ impl Repository {
19821992
}
19831993

19841994
pub async fn get_pr(&self, client: &GithubClient, pr_num: u64) -> anyhow::Result<Issue> {
1985-
let url = format!("{}/pulls/{pr_num}", self.url(client));
1986-
let mut pr: Issue = client
1987-
.json(client.get(&url))
1995+
client
1996+
.pull_request(
1997+
&IssueRepository {
1998+
organization: self.owner().to_string(),
1999+
repository: self.name().to_string(),
2000+
},
2001+
pr_num,
2002+
)
19882003
.await
1989-
.with_context(|| format!("{} failed to get pr {pr_num}", self.full_name))?;
1990-
pr.pull_request = Some(PullRequestDetails::new());
1991-
Ok(pr)
19922004
}
19932005

19942006
/// Fetches information about merge conflicts on open PRs.

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ pub mod bors;
66
mod changelogs;
77
mod config;
88
pub mod db;
9+
pub mod gh_changes_since;
910
pub mod gh_range_diff;
1011
pub mod gha_logs;
1112
pub mod github;

src/main.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,10 @@ async fn run_server(addr: SocketAddr) -> anyhow::Result<()> {
193193
"/gh-range-diff/{owner}/{repo}/{oldbasehead}/{newbasehead}",
194194
get(triagebot::gh_range_diff::gh_ranges_diff),
195195
)
196+
.route(
197+
"/gh-changes-since/{owner}/{repo}/{pr}/{oldbasehead}",
198+
get(triagebot::gh_changes_since::gh_changes_since),
199+
)
196200
.nest("/agenda", agenda)
197201
.route("/bors-commit-list", get(triagebot::bors::bors_commit_list))
198202
.route(

0 commit comments

Comments
 (0)