diff --git a/parser/src/command/relabel.rs b/parser/src/command/relabel.rs index 7e7abae14..7154c7926 100644 --- a/parser/src/command/relabel.rs +++ b/parser/src/command/relabel.rs @@ -102,7 +102,6 @@ fn delta_empty() { } impl RelabelCommand { - /// Parse and validate command tokens pub fn parse<'a>(input: &mut Tokenizer<'a>) -> Result, Error<'a>> { let mut toks = input.clone(); diff --git a/src/config.rs b/src/config.rs index ccc904aa0..cb43f769b 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,6 +1,5 @@ use crate::changelogs::ChangelogFormat; use crate::github::{GithubClient, Repository}; -use parser::command::relabel::{Label, LabelDelta, RelabelCommand}; use std::collections::{HashMap, HashSet}; use std::fmt; use std::sync::{Arc, LazyLock, RwLock}; @@ -251,64 +250,10 @@ pub(crate) struct MentionsEntryConfig { #[derive(PartialEq, Eq, Debug, serde::Deserialize)] #[serde(rename_all = "kebab-case")] +#[serde(deny_unknown_fields)] pub(crate) struct RelabelConfig { #[serde(default)] pub(crate) allow_unauthenticated: Vec, - // alias identifier -> labels - #[serde(flatten)] - pub(crate) aliases: HashMap, -} - -impl RelabelConfig { - pub(crate) fn retrieve_command_from_alias(&self, input: RelabelCommand) -> RelabelCommand { - let mut deltas = vec![]; - if !self.aliases.is_empty() { - // parse all tokens: if one matches an alias, extract the labels - // else, it will assumed to be a valid label - for tk in input.0.into_iter() { - let name = tk.label() as &str; - if let Some(alias) = self.aliases.get(name) { - let cmd = alias.to_command(matches!(tk, LabelDelta::Remove(_))); - deltas.extend(cmd.0); - } else { - deltas.push(tk); - } - } - } - RelabelCommand(deltas) - } -} - -#[derive(Default, PartialEq, Eq, Debug, serde::Deserialize)] -#[serde(rename_all = "kebab-case")] -#[serde(deny_unknown_fields)] -pub(crate) struct RelabelAliasConfig { - /// Labels to be added - pub(crate) add_labels: Vec, - /// Labels to be removed - pub(crate) rem_labels: Vec, -} - -impl RelabelAliasConfig { - /// Translate a RelabelAliasConfig into a RelabelCommand for GitHub consumption - fn to_command(&self, inverted: bool) -> RelabelCommand { - let mut deltas = Vec::new(); - let mut add_labels = &self.add_labels; - let mut rem_labels = &self.rem_labels; - - // if the polarity of the alias is inverted, swap labels before parsing the command - if inverted { - std::mem::swap(&mut add_labels, &mut rem_labels); - } - - for l in add_labels.iter() { - deltas.push(LabelDelta::Add(Label(l.into()))); - } - for l in rem_labels.iter() { - deltas.push(LabelDelta::Remove(Label(l.into()))); - } - RelabelCommand(deltas) - } } #[derive(PartialEq, Eq, Debug, serde::Deserialize)] @@ -816,11 +761,11 @@ mod tests { [mentions."src/"] cc = ["@someone"] - + [mentions."target/"] message = "This is a message." cc = ["@someone"] - + [mentions."#[rustc_attr]"] type = "content" message = "This is a message." @@ -890,7 +835,6 @@ mod tests { Config { relabel: Some(RelabelConfig { allow_unauthenticated: vec!["C-*".into()], - aliases: HashMap::new() }), assign: Some(AssignConfig { warn_non_default_branch: WarnNonDefaultBranchConfig::Simple(false), @@ -1089,76 +1033,6 @@ mod tests { ); } - #[test] - fn relabel_alias_config() { - let config = r#" - [relabel.to-stable] - add-labels = ["regression-from-stable-to-stable"] - rem-labels = ["regression-from-stable-to-beta", "regression-from-stable-to-nightly"] - "#; - let config = toml::from_str::(&config).unwrap(); - - let mut relabel_configs = HashMap::new(); - relabel_configs.insert( - "to-stable".into(), - RelabelAliasConfig { - add_labels: vec!["regression-from-stable-to-stable".to_string()], - rem_labels: vec![ - "regression-from-stable-to-beta".to_string(), - "regression-from-stable-to-nightly".to_string(), - ], - }, - ); - - let expected_cfg = RelabelConfig { - allow_unauthenticated: vec![], - aliases: relabel_configs, - }; - - assert_eq!(config.relabel, Some(expected_cfg)); - } - - #[test] - fn relabel_alias() { - // [relabel.my-alias] - // add-labels = ["Alpha"] - // rem-labels = ["Bravo", "Charlie"] - let relabel_cfg = RelabelConfig { - allow_unauthenticated: vec![], - aliases: HashMap::from([( - "my-alias".to_string(), - RelabelAliasConfig { - add_labels: vec!["Alpha".to_string()], - rem_labels: vec!["Bravo".to_string(), "Charlie".to_string()], - }, - )]), - }; - - // @triagebot label my-alias - let deltas = vec![LabelDelta::Add(Label("my-alias".into()))]; - let new_input = relabel_cfg.retrieve_command_from_alias(RelabelCommand(deltas)); - assert_eq!( - new_input, - RelabelCommand(vec![ - LabelDelta::Add(Label("Alpha".into())), - LabelDelta::Remove(Label("Bravo".into())), - LabelDelta::Remove(Label("Charlie".into())), - ]) - ); - - // @triagebot label -my-alias - let deltas = vec![LabelDelta::Remove(Label("my-alias".into()))]; - let new_input = relabel_cfg.retrieve_command_from_alias(RelabelCommand(deltas)); - assert_eq!( - new_input, - RelabelCommand(vec![ - LabelDelta::Add(Label("Bravo".into())), - LabelDelta::Add(Label("Charlie".into())), - LabelDelta::Remove(Label("Alpha".into())), - ]) - ); - } - #[test] fn issue_links_uncanonicalized() { let config = r#" @@ -1219,36 +1093,4 @@ Multi text body with ${mcp_issue} and ${mcp_title} }) ); } - - #[test] - fn relabel_new_config() { - let config = r#" - [relabel] - allow-unauthenticated = ["ABCD-*"] - - [relabel.to-stable] - add-labels = ["regression-from-stable-to-stable"] - rem-labels = ["regression-from-stable-to-beta", "regression-from-stable-to-nightly"] - "#; - let config = toml::from_str::(&config).unwrap(); - - let mut relabel_configs = HashMap::new(); - relabel_configs.insert( - "to-stable".into(), - RelabelAliasConfig { - add_labels: vec!["regression-from-stable-to-stable".to_string()], - rem_labels: vec![ - "regression-from-stable-to-beta".to_string(), - "regression-from-stable-to-nightly".to_string(), - ], - }, - ); - - let expected_cfg = RelabelConfig { - allow_unauthenticated: vec!["ABCD-*".to_string()], - aliases: relabel_configs, - }; - - assert_eq!(config.relabel, Some(expected_cfg)); - } } diff --git a/src/github.rs b/src/github.rs index 4d63f4c27..5c4c4e3a6 100644 --- a/src/github.rs +++ b/src/github.rs @@ -1338,6 +1338,9 @@ impl IssuesEvent { } } +#[derive(Debug, serde::Deserialize)] +struct PullRequestEventFields {} + #[derive(Debug, serde::Deserialize)] pub struct WorkflowRunJob { pub name: String, diff --git a/src/handlers/relabel.rs b/src/handlers/relabel.rs index d0478650d..d76725bc7 100644 --- a/src/handlers/relabel.rs +++ b/src/handlers/relabel.rs @@ -1,7 +1,7 @@ -//! Purpose: Allow any user to modify labels on GitHub issues and pull requests via comments. +//! Purpose: Allow any user to modify issue labels on GitHub via comments. //! -//! Labels are checked against the existing set in the git repository; the bot does not support -//! creating new labels. +//! Labels are checked against the labels in the project; the bot does not support creating new +//! labels. //! //! Parsing is done in the `parser::command::relabel` module. //! @@ -27,17 +27,13 @@ pub(super) async fn handle_command( input: RelabelCommand, ) -> anyhow::Result<()> { let Some(issue) = event.issue() else { - return user_error!("Can only add and remove labels on issues and pull requests"); + return user_error!("Can only add and remove labels on an issue"); }; - // If the input matches a valid alias, read the [relabel] config. - // if any alias matches, extract the alias config (RelabelAliasConfig) and build a new RelabelCommand. - let new_input = config.retrieve_command_from_alias(input); - // Check label authorization for the current user - for delta in &new_input.0 { + 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) { + let err = match check_filter(name, config, is_member(event.user(), &ctx.team).await) { Ok(CheckFilterResult::Allow) => None, Ok(CheckFilterResult::Deny) => { Some(format!("Label {name} can only be set by Rust team members")) @@ -48,7 +44,6 @@ pub(super) async fn handle_command( )), Err(err) => Some(err), }; - if let Some(err) = err { // bail-out and inform the user why return user_error!(err); @@ -56,7 +51,7 @@ pub(super) async fn handle_command( } // Compute the labels to add and remove - let (to_add, to_remove) = compute_label_deltas(&new_input.0); + let (to_add, to_remove) = compute_label_deltas(&input.0); // Add labels if let Err(e) = issue.add_labels(&ctx.github, to_add.clone()).await { @@ -108,8 +103,6 @@ enum CheckFilterResult { DenyUnknown, } -/// Check if the team member is allowed to apply labels -/// configured in `allow_unauthenticated` fn check_filter( label: &str, config: &RelabelConfig, @@ -201,7 +194,6 @@ fn compute_label_deltas(deltas: &[LabelDelta]) -> (Vec