Skip to content

Commit 159f9c3

Browse files
committed
Post comment to our range-diff when the PR was rebased.
1 parent 9d01775 commit 159f9c3

File tree

7 files changed

+100
-7
lines changed

7 files changed

+100
-7
lines changed

src/config.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ pub(crate) struct Config {
4848
pub(crate) no_mentions: Option<NoMentionsConfig>,
4949
pub(crate) behind_upstream: Option<BehindUpstreamConfig>,
5050
pub(crate) backport: Option<BackportConfig>,
51+
pub(crate) range_diff: Option<RangeDiffConfig>,
5152
}
5253

5354
#[derive(PartialEq, Eq, Debug, serde::Deserialize)]
@@ -551,6 +552,12 @@ pub(crate) struct BackportRuleConfig {
551552
pub(crate) add_labels: Vec<String>,
552553
}
553554

555+
/// Configuration for rebase range-diff comment
556+
#[derive(Default, PartialEq, Eq, Debug, serde::Deserialize)]
557+
#[serde(rename_all = "kebab-case")]
558+
#[serde(deny_unknown_fields)]
559+
pub(crate) struct RangeDiffConfig {}
560+
554561
fn get_cached_config(repo: &str) -> Option<Result<Arc<Config>, ConfigurationError>> {
555562
let cache = CONFIG_CACHE.read().unwrap();
556563
cache.get(repo).and_then(|(config, fetch_time)| {
@@ -689,6 +696,8 @@ mod tests {
689696
required-pr-labels = ["T-libs", "T-libs-api"]
690697
required-issue-label = "regression-from-stable-to-stable"
691698
add-labels = ["stable-nominated"]
699+
700+
[range-diff]
692701
"#;
693702
let config = toml::from_str::<Config>(&config).unwrap();
694703
let mut ping_teams = HashMap::new();
@@ -776,7 +785,8 @@ mod tests {
776785
concern: Some(ConcernConfig {
777786
labels: vec!["has-concerns".to_string()],
778787
}),
779-
backport: Some(backport_team_config)
788+
backport: Some(backport_team_config),
789+
range_diff: Some(RangeDiffConfig {}),
780790
}
781791
);
782792
}
@@ -864,7 +874,8 @@ mod tests {
864874
behind_upstream: Some(BehindUpstreamConfig {
865875
days_threshold: Some(7),
866876
}),
867-
backport: None
877+
backport: None,
878+
range_diff: None,
868879
}
869880
);
870881
}

src/github.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1268,6 +1268,8 @@ pub struct IssuesEvent {
12681268
#[serde(alias = "pull_request")]
12691269
pub issue: Issue,
12701270
pub changes: Option<Changes>,
1271+
pub before: Option<String>,
1272+
pub after: Option<String>,
12711273
pub repository: Repository,
12721274
/// The GitHub user that triggered the event.
12731275
pub sender: User,

src/github/webhook.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use std::{fmt, sync::Arc};
22

33
use axum::{extract::State, response::IntoResponse};
4+
use axum_extra::extract::Host;
45
use hmac::{Hmac, Mac};
56
use hyper::HeaderMap;
67
use sha2::Sha256;
@@ -106,6 +107,7 @@ pub fn deserialize_payload<T: serde::de::DeserializeOwned>(v: &str) -> anyhow::R
106107
pub async fn webhook(
107108
headers: HeaderMap,
108109
State(ctx): State<Arc<crate::handlers::Context>>,
110+
Host(host): Host,
109111
body: Bytes,
110112
) -> axum::response::Response {
111113
// Extract X-GitHub-Event header
@@ -156,7 +158,7 @@ pub async fn webhook(
156158
return (StatusCode::BAD_REQUEST, "Payload must be UTF-8").into_response();
157159
};
158160

159-
match process_payload(event, payload, &ctx).await {
161+
match process_payload(event, payload, &ctx, &host).await {
160162
Ok(true) => ("processed request",).into_response(),
161163
Ok(false) => ("ignored request",).into_response(),
162164
Err(err) => {
@@ -171,6 +173,7 @@ async fn process_payload(
171173
event: EventName,
172174
payload: &str,
173175
ctx: &crate::handlers::Context,
176+
host: &str,
174177
) -> anyhow::Result<bool> {
175178
let event = match event {
176179
EventName::PullRequestReview => {
@@ -253,7 +256,7 @@ async fn process_payload(
253256
return Ok(false);
254257
}
255258
};
256-
let errors = crate::handlers::handle(&ctx, &event).await;
259+
let errors = crate::handlers::handle(&ctx, &host, &event).await;
257260
let mut other_error = false;
258261
let mut message = String::new();
259262
for err in errors {

src/handlers.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ mod shortcut;
6060
mod transfer;
6161
pub mod types_planning_updates;
6262

63-
pub async fn handle(ctx: &Context, event: &Event) -> Vec<HandlerError> {
63+
pub async fn handle(ctx: &Context, host: &str, event: &Event) -> Vec<HandlerError> {
6464
let config = config::get(&ctx.github, event.repo()).await;
6565
if let Err(e) = &config {
6666
log::warn!("configuration error {}: {e}", event.repo().full_name);
@@ -76,7 +76,7 @@ pub async fn handle(ctx: &Context, event: &Event) -> Vec<HandlerError> {
7676
}
7777

7878
if let Ok(config) = &config {
79-
if let Err(e) = check_commits::handle(ctx, event, &config).await {
79+
if let Err(e) = check_commits::handle(ctx, host, event, &config).await {
8080
log::error!(
8181
"failed to process event {:?} with `check_commits` handler: {:?}",
8282
event,

src/handlers/check_commits.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use crate::{
1515
use crate::github::GithubCommit;
1616

1717
mod behind_upstream;
18+
mod force_push_range_diff;
1819
mod issue_links;
1920
mod modified_submodule;
2021
mod no_mentions;
@@ -69,7 +70,12 @@ fn should_handle_event(event: &IssuesEvent) -> bool {
6970
false
7071
}
7172

72-
pub(super) async fn handle(ctx: &Context, event: &Event, config: &Config) -> anyhow::Result<()> {
73+
pub(super) async fn handle(
74+
ctx: &Context,
75+
host: &str,
76+
event: &Event,
77+
config: &Config,
78+
) -> anyhow::Result<()> {
7379
let Event::Issue(event) = event else {
7480
return Ok(());
7581
};
@@ -135,6 +141,12 @@ pub(super) async fn handle(ctx: &Context, event: &Event, config: &Config) -> any
135141
}
136142
}
137143

144+
// Check if this is a force-push with rebase and if it is emit comment
145+
// with link to our range-diff viewer.
146+
if let Some(range_diff) = &config.range_diff {
147+
force_push_range_diff::handle_event(ctx, host, range_diff, &event, &compare).await?;
148+
}
149+
138150
// Check if the `triagebot.toml` config is valid
139151
errors.extend(
140152
validate_config::validate_config(ctx, &event, diff)
@@ -408,6 +420,8 @@ r#":warning: **Warning** :warning:
408420
author_association: octocrab::models::AuthorAssociation::Contributor,
409421
},
410422
changes: None,
423+
before: None,
424+
after: None,
411425
repository: crate::github::Repository {
412426
full_name: "rust-lang/rust".to_string(),
413427
default_branch: "master".to_string(),
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
use anyhow::Context as _;
2+
3+
use crate::config::RangeDiffConfig;
4+
use crate::github::GithubCompare;
5+
use crate::github::IssueRepository;
6+
use crate::github::IssuesEvent;
7+
use crate::handlers::Context;
8+
9+
pub(super) async fn handle_event(
10+
ctx: &Context,
11+
host: &str,
12+
_config: &RangeDiffConfig,
13+
event: &IssuesEvent,
14+
compare_after: &GithubCompare,
15+
) -> anyhow::Result<()> {
16+
if !matches!(event.action, crate::github::IssuesAction::Synchronize) {
17+
return Ok(());
18+
}
19+
20+
let (Some(before), Some(after)) = (event.before.as_ref(), event.after.as_ref()) else {
21+
tracing::warn!("synchronize event but no before or after field");
22+
return Ok(());
23+
};
24+
25+
let base = event.issue.base.as_ref().context("no base ref")?;
26+
let org = event.repository.owner();
27+
let repo = event.repository.name();
28+
29+
let compare_before = ctx
30+
.github
31+
.compare(
32+
&IssueRepository {
33+
organization: org.to_string(),
34+
repository: repo.to_string(),
35+
},
36+
&base.sha,
37+
&before,
38+
)
39+
.await
40+
.context("failed to get the before compare")?;
41+
42+
// Does the merge_base_commits differs? No, not a force-push with rebase.
43+
if compare_before.merge_base_commit.sha == compare_after.merge_base_commit.sha {
44+
return Ok(());
45+
}
46+
47+
let protocol = if host.starts_with("localhost:") {
48+
"http"
49+
} else {
50+
"https"
51+
};
52+
53+
let branch = &base.git_ref;
54+
55+
// Rebase detected, post a comment to our range-diff.
56+
event.issue.post_comment(&ctx.github,
57+
&format!(r#"This PR was rebased onto a different {branch} commit! Check out the changes with our [`range-diff`]({protocol}://{host}/gh-range-diff/{org}/{repo}/{before}..{after})."#)
58+
).await.context("failed to post range-diff comment")?;
59+
60+
Ok(())
61+
}

src/handlers/pr_tracking.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,8 @@ mod tests {
571571
action,
572572
issue,
573573
changes: None,
574+
before: None,
575+
after: None,
574576
repository: Repository {
575577
full_name: "rust-lang-test/triagebot-test".to_string(),
576578
default_branch: "main".to_string(),

0 commit comments

Comments
 (0)