From 18dabcfb2c6165ee44957fc3375815f64fb16f93 Mon Sep 17 00:00:00 2001 From: Urgau Date: Tue, 30 Sep 2025 14:27:30 +0200 Subject: [PATCH 1/2] Make relabel deltas left to right consistent --- parser/src/command/relabel.rs | 2 +- src/github.rs | 2 +- src/handlers/relabel.rs | 113 ++++++++++++++++++++++++++++------ 3 files changed, 97 insertions(+), 20 deletions(-) diff --git a/parser/src/command/relabel.rs b/parser/src/command/relabel.rs index ef5a305c2..1c89f1254 100644 --- a/parser/src/command/relabel.rs +++ b/parser/src/command/relabel.rs @@ -19,7 +19,7 @@ pub enum LabelDelta { } #[derive(Debug, PartialEq, Eq, Clone)] -pub struct Label(String); +pub struct Label(pub String); #[derive(PartialEq, Eq, Debug)] pub enum ParseError { diff --git a/src/github.rs b/src/github.rs index aa9af700b..0ef421604 100644 --- a/src/github.rs +++ b/src/github.rs @@ -324,7 +324,7 @@ impl User { } } -#[derive(PartialEq, Eq, Debug, Clone, serde::Deserialize)] +#[derive(PartialEq, Eq, Debug, Clone, Ord, PartialOrd, serde::Deserialize)] pub struct Label { pub name: String, } diff --git a/src/handlers/relabel.rs b/src/handlers/relabel.rs index 31c5908e8..f12519351 100644 --- a/src/handlers/relabel.rs +++ b/src/handlers/relabel.rs @@ -8,6 +8,9 @@ //! If the command was successful, there will be no feedback beyond the label change to reduce //! notification noise. +use std::collections::BTreeSet; + +use crate::github::Label; use crate::team_data::TeamClient; use crate::{ config::RelabelConfig, @@ -24,8 +27,6 @@ pub(super) async fn handle_command( event: &Event, input: RelabelCommand, ) -> anyhow::Result<()> { - let mut results = vec![]; - let mut to_add = vec![]; for delta in &input.0 { let name = delta.label().as_str(); let err = match check_filter(name, config, is_member(&event.user(), &ctx.team).await) { @@ -46,21 +47,10 @@ pub(super) async fn handle_command( cmnt.post(&ctx.github).await?; return Ok(()); } - match delta { - LabelDelta::Add(label) => { - to_add.push(github::Label { - name: label.to_string(), - }); - } - LabelDelta::Remove(label) => { - results.push(( - label, - event.issue().unwrap().remove_label(&ctx.github, &label), - )); - } - } } + let (to_add, to_remove) = compute_label_deltas(&input.0); + if let Err(e) = event .issue() .unwrap() @@ -84,8 +74,13 @@ pub(super) async fn handle_command( return Err(e); } - for (label, res) in results { - if let Err(e) = res.await { + for label in to_remove { + if let Err(e) = event + .issue() + .unwrap() + .remove_label(&ctx.github, &label.name) + .await + { tracing::error!( "failed to remove {:?} from issue {}: {:?}", label, @@ -182,10 +177,41 @@ fn match_pattern(pattern: &str, label: &str) -> anyhow::Result (Vec