Skip to content

Commit 26e7bca

Browse files
committed
Fix backport handler
- Handles when a backport label is added - Fixes preliminary check on backport labels
1 parent c19f6d7 commit 26e7bca

File tree

2 files changed

+56
-18
lines changed

2 files changed

+56
-18
lines changed

src/handlers/backport.rs

Lines changed: 52 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
1+
//! Handles stable, beta backports for PRs fixing P-high/critical regressions
2+
//!
3+
//! Add proper labels, opens a poll on Zulip to gauge interest about a backport.
4+
//! Posts a closing messages on Zulip when the PR has been backport accepted.
5+
//!
6+
//! Configuration is done with the `[backport]` table.
7+
//!
18
use std::collections::HashMap;
29
use std::sync::LazyLock;
310

411
use crate::config::BackportConfig;
512
use crate::github::{IssuesAction, IssuesEvent, Label};
613
use crate::handlers::Context;
14+
use crate::utils::contains_any;
715
use anyhow::Context as AnyhowContext;
816
use futures::future::join_all;
917
use regex::Regex;
@@ -15,12 +23,9 @@ static CLOSES_ISSUE_REGEXP: LazyLock<Regex> = LazyLock::new(|| {
1523
Regex::new("(?i)(?P<action>close[sd]*|fix([e]*[sd]*)?|resolve[sd]*)(?P<spaces>:? +)(?P<org_repo>[a-zA-Z0-9_-]*/[a-zA-Z0-9_-]*)?#(?P<issue_num>[0-9]+)").unwrap()
1624
});
1725

18-
const BACKPORT_LABELS: [&str; 4] = [
19-
"beta-nominated",
20-
"beta-accepted",
21-
"stable-nominated",
22-
"stable-accepted",
23-
];
26+
const BACKPORT_ACCEPTED_LABELS: [&str; 2] = ["beta-accepted", "stable-accepted"];
27+
28+
const BACKPORT_NOMINATED_LABELS: [&str; 2] = ["beta-nominated", "stable-nominated"];
2429

2530
const REGRESSION_LABELS: [&str; 3] = [
2631
"regression-from-stable-to-nightly",
@@ -53,13 +58,17 @@ pub(super) async fn parse_input(
5358
// - is opened (and not a draft)
5459
// - is converted from draft to ready for review
5560
// - when the first comment is edited
61+
// - when a label is added (later we check which one)
5662
let skip_check = !matches!(
5763
event.action,
58-
IssuesAction::Opened | IssuesAction::Edited | IssuesAction::ReadyForReview
64+
IssuesAction::Opened
65+
| IssuesAction::Edited
66+
| IssuesAction::ReadyForReview
67+
| IssuesAction::Labeled { label: _ }
5968
);
6069
if skip_check || !event.issue.is_pr() || event.issue.draft {
6170
log::debug!(
62-
"Skipping backport event because: IssuesAction = {:?}, issue.is_pr() {}, draft = {}",
71+
"Skipping backport event because: IssuesAction = {:?}, issue.is_pr() = {}, draft = {}",
6372
event.action,
6473
event.issue.is_pr(),
6574
event.issue.draft
@@ -69,9 +78,37 @@ pub(super) async fn parse_input(
6978
let pr = &event.issue;
7079

7180
let pr_labels: Vec<&str> = pr.labels.iter().map(|l| l.name.as_str()).collect();
72-
if contains_any(&pr_labels, &BACKPORT_LABELS) {
73-
log::debug!("PR #{} already has a backport label", pr.number);
74-
return Ok(None);
81+
82+
// if adding a "-nominated" label to a PR, proceed if PR does not have it already
83+
// (we don't check for "-accepted" labels)
84+
if let IssuesAction::Labeled { label } = &event.action
85+
&& BACKPORT_NOMINATED_LABELS.contains(&label.name.as_str())
86+
{
87+
if contains_any(&pr_labels, &BACKPORT_NOMINATED_LABELS) {
88+
log::debug!(
89+
"PR #{} is already backport nominated (found labels: {:?})",
90+
pr.number,
91+
pr_labels
92+
);
93+
// NOTE: this won't revert the label added by github
94+
return Ok(None);
95+
}
96+
}
97+
98+
// If adding an "-accepted" label to a PR, proceed if PR does not have it already
99+
// (we skip checking the "-nominated" labels, sometimes T-release straight backport accepts PRs)
100+
if let IssuesAction::Labeled { label } = &event.action
101+
&& BACKPORT_ACCEPTED_LABELS.contains(&label.name.as_str())
102+
{
103+
if contains_any(&pr_labels, &BACKPORT_ACCEPTED_LABELS) {
104+
log::debug!(
105+
"PR #{} is already backport accepted (found labels: {:?})",
106+
pr.number,
107+
pr_labels
108+
);
109+
// NOTE: this won't revert the label added by github
110+
return Ok(None);
111+
}
75112
}
76113

77114
// Retrieve backport config for this PR, based on its team label(s)
@@ -187,7 +224,8 @@ pub(super) async fn handle_input(
187224
continue;
188225
}
189226

190-
// Add backport nomination label(s) to PR
227+
// When backport nominating/accepting a PR, if a `[notify-zulip]` table is configured in triagebot.toml
228+
// that will trigger the notify_zulip handler
191229
let mut new_labels = pr.labels().to_owned();
192230
new_labels.extend(
193231
add_labels
@@ -210,16 +248,12 @@ pub(super) async fn handle_input(
210248
Ok(())
211249
}
212250

213-
fn contains_any(haystack: &[&str], needles: &[&str]) -> bool {
214-
needles.iter().any(|needle| haystack.contains(needle))
215-
}
216-
217251
#[cfg(test)]
218252
mod tests {
219253
use crate::handlers::backport::CLOSES_ISSUE_REGEXP;
220254

221-
#[tokio::test]
222-
async fn backport_match_comment() {
255+
#[test]
256+
fn backport_match_comment() {
223257
let test_strings = vec![
224258
("close #10", vec![10]),
225259
("closes #10", vec![10]),

src/utils.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,3 +56,7 @@ pub(crate) async fn is_issue_under_rfcbot_fcp(
5656

5757
false
5858
}
59+
60+
pub fn contains_any(haystack: &[&str], needles: &[&str]) -> bool {
61+
needles.iter().any(|needle| haystack.contains(needle))
62+
}

0 commit comments

Comments
 (0)