From 7fb447a92be4d67856972785a133d25c7591c0f3 Mon Sep 17 00:00:00 2001 From: Peter Jaszkowiak Date: Fri, 15 Sep 2023 21:10:39 -0600 Subject: [PATCH 1/6] no-merges: match titles instead of labels also don't re-add labels if they're manually removed labels are not always set atomically when opening a PR example: rust-lang/miri#3059 --- src/config.rs | 4 ++-- src/handlers/no_merges.rs | 42 ++++++++++++++++++++++++++++----------- 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/src/config.rs b/src/config.rs index 38e81fce..3386c32a 100644 --- a/src/config.rs +++ b/src/config.rs @@ -105,9 +105,9 @@ impl AssignConfig { #[derive(PartialEq, Eq, Debug, serde::Deserialize)] pub(crate) struct NoMergesConfig { - /// No action will be taken on PRs with these labels. + /// No action will be taken on PRs with these substrings in the title. #[serde(default)] - pub(crate) exclude_labels: Vec, + pub(crate) exclude_titles: Vec, /// Set these labels on the PR when merge commits are detected. #[serde(default)] pub(crate) labels: Vec, diff --git a/src/handlers/no_merges.rs b/src/handlers/no_merges.rs index e90008cd..9856c871 100644 --- a/src/handlers/no_merges.rs +++ b/src/handlers/no_merges.rs @@ -48,11 +48,13 @@ pub(super) async fn parse_input( return Ok(None); } - // Don't trigger if the PR has any of the excluded labels. - for label in event.issue.labels() { - if config.exclude_labels.contains(&label.name) { - return Ok(None); - } + // Don't trigger if the PR has any of the excluded title segments. + if config + .exclude_titles + .iter() + .any(|s| event.issue.title.contains(s)) + { + return Ok(None); } let mut merge_commits = HashSet::new(); @@ -70,12 +72,11 @@ pub(super) async fn parse_input( } } - let input = NoMergesInput { merge_commits }; - Ok(if input.merge_commits.is_empty() { - None - } else { - Some(input) - }) + if merge_commits.is_empty() { + return Ok(None); + } + + Ok(Some(NoMergesInput { merge_commits })) } const DEFAULT_MESSAGE: &str = " @@ -102,6 +103,7 @@ pub(super) async fn handle_input( let mut client = ctx.db.get().await; let mut state: IssueData<'_, NoMergesState> = IssueData::load(&mut client, &event.issue, NO_MERGES_KEY).await?; + let first_time = state.data.mentioned_merge_commits.is_empty(); let mut message = config .message @@ -109,7 +111,7 @@ pub(super) async fn handle_input( .unwrap_or(DEFAULT_MESSAGE) .to_string(); - let since_last_posted = if state.data.mentioned_merge_commits.is_empty() { + let since_last_posted = if first_time { "" } else { " (since this message was last posted)" @@ -132,6 +134,22 @@ pub(super) async fn handle_input( } if should_send { + if !first_time { + // Check if the labels are still set. + // Otherwise, they were probably removed manually. + let any_removed = config.labels.iter().any(|label| { + // No label on the issue matches. + event.issue.labels().iter().all(|l| &l.name != label) + }); + + if any_removed { + // Assume it was a false positive, so don't + // re-add the labels or send a message this time. + state.save().await?; + return Ok(()); + } + } + // Set labels let labels = config .labels From 559e1d37b23c113d7d5574bf708ca6e4a489a742 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Sun, 15 Oct 2023 12:48:24 +0200 Subject: [PATCH 2/6] Make `IssuesAction` into a dataful enum, to remove unwraps --- src/github.rs | 22 ++++++++++++++++------ src/handlers/autolabel.rs | 4 ++-- src/handlers/major_change.rs | 19 +++---------------- src/handlers/notify_zulip.rs | 18 ++++++++++-------- 4 files changed, 31 insertions(+), 32 deletions(-) diff --git a/src/github.rs b/src/github.rs index 496a214e..f46b8d55 100644 --- a/src/github.rs +++ b/src/github.rs @@ -911,7 +911,7 @@ pub struct IssueCommentEvent { } #[derive(PartialEq, Eq, Debug, serde::Deserialize)] -#[serde(rename_all = "snake_case")] +#[serde(rename_all = "snake_case", tag = "action")] pub enum IssuesAction { Opened, Edited, @@ -923,13 +923,22 @@ pub enum IssuesAction { Reopened, Assigned, Unassigned, - Labeled, - Unlabeled, + Labeled { + /// The label added from the issue + label: Label, + }, + Unlabeled { + /// The label removed from the issue + label: Label, + }, Locked, Unlocked, Milestoned, Demilestoned, - ReviewRequested, + ReviewRequested { + /// The person requested to review the pull request + requested_reviewer: User, + }, ReviewRequestRemoved, ReadyForReview, Synchronize, @@ -940,13 +949,14 @@ pub enum IssuesAction { #[derive(Debug, serde::Deserialize)] pub struct IssuesEvent { + #[serde(flatten)] pub action: IssuesAction, #[serde(alias = "pull_request")] pub issue: Issue, pub changes: Option, pub repository: Repository, - /// Some if action is IssuesAction::Labeled, for example - pub label: Option