From bed908a2a5534ef1bb667cfdbe09239e974ff2ee Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sun, 12 May 2019 17:53:51 -0600 Subject: [PATCH 1/2] Add triage command This command is intended for the addition of priority tags (high/medium/low) while removing some set of tags, usually a nomination. --- parser/src/command.rs | 8 ++++ parser/src/command/triage.rs | 77 ++++++++++++++++++++++++++++++++++++ src/config.rs | 10 +++++ src/handlers.rs | 2 + src/handlers/triage.rs | 48 ++++++++++++++++++++++ 5 files changed, 145 insertions(+) create mode 100644 parser/src/command/triage.rs create mode 100644 src/handlers/triage.rs diff --git a/parser/src/command.rs b/parser/src/command.rs index 7edde0f60..05125974b 100644 --- a/parser/src/command.rs +++ b/parser/src/command.rs @@ -11,6 +11,7 @@ pub mod prioritize; pub mod relabel; pub mod second; pub mod shortcut; +pub mod triage; pub fn find_command_start(input: &str, bot: &str) -> Option { input.to_ascii_lowercase().find(&format!("@{}", bot)) @@ -27,6 +28,7 @@ pub enum Command<'a> { Glacier(Result>), Shortcut(Result>), Close(Result>), + Triage(Result>), } #[derive(Debug)] @@ -131,6 +133,11 @@ impl<'a> Input<'a> { Command::Close, &original_tokenizer, )); + success.extend(parse_single_command( + triage::TriageCommand::parse, + Command::Triage, + &original_tokenizer, + )); if success.len() > 1 { panic!( @@ -191,6 +198,7 @@ impl<'a> Command<'a> { Command::Glacier(r) => r.is_ok(), Command::Shortcut(r) => r.is_ok(), Command::Close(r) => r.is_ok(), + Command::Triage(r) => r.is_ok(), } } diff --git a/parser/src/command/triage.rs b/parser/src/command/triage.rs new file mode 100644 index 000000000..d0175e9e9 --- /dev/null +++ b/parser/src/command/triage.rs @@ -0,0 +1,77 @@ +//! The triage command parser. +//! +//! Gives the priority to be changed to. +//! +//! The grammar is as follows: +//! +//! ```text +//! Command: `@bot triage {high,medium,low,P-high,P-medium,P-low}` +//! ``` + +use crate::error::Error; +use crate::token::{Token, Tokenizer}; +use std::fmt; + +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub enum Priority { + High, + Low, + Medium, +} + +#[derive(PartialEq, Eq, Debug)] +pub struct TriageCommand { + pub priority: Priority, +} + +#[derive(PartialEq, Eq, Debug)] +pub enum ParseError { + ExpectedPriority, + ExpectedEnd, +} + +impl std::error::Error for ParseError {} + +impl fmt::Display for ParseError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + ParseError::ExpectedPriority => write!(f, "expected priority (high, medium, low)"), + ParseError::ExpectedEnd => write!(f, "expected end of command"), + } + } +} + +impl TriageCommand { + pub fn parse<'a>(input: &mut Tokenizer<'a>) -> Result, Error<'a>> { + let mut toks = input.clone(); + if let Some(Token::Word("triage")) = toks.peek_token()? { + toks.next_token()?; + let priority = match toks.peek_token()? { + Some(Token::Word("high")) | Some(Token::Word("P-high")) => { + toks.next_token()?; + Priority::High + } + Some(Token::Word("medium")) | Some(Token::Word("P-medium")) => { + toks.next_token()?; + Priority::Medium + } + Some(Token::Word("low")) | Some(Token::Word("P-low")) => { + toks.next_token()?; + Priority::Low + } + _ => { + return Err(toks.error(ParseError::ExpectedPriority)); + } + }; + if let Some(Token::Dot) | Some(Token::EndOfLine) = toks.peek_token()? { + toks.next_token()?; + *input = toks; + return Ok(Some(TriageCommand { priority: priority })); + } else { + return Err(toks.error(ParseError::ExpectedEnd)); + } + } else { + return Ok(None); + } + } +} diff --git a/src/config.rs b/src/config.rs index 176e92275..51d762d28 100644 --- a/src/config.rs +++ b/src/config.rs @@ -30,6 +30,7 @@ pub(crate) struct Config { pub(crate) github_releases: Option, pub(crate) review_submitted: Option, pub(crate) shortcut: Option, + pub(crate) triage: Option, } #[derive(PartialEq, Eq, Debug, serde::Deserialize)] @@ -158,6 +159,14 @@ pub(crate) struct ReviewSubmittedConfig { pub(crate) reviewed_label: String, } +#[derive(PartialEq, Eq, Debug, serde::Deserialize)] +pub(crate) struct TriageConfig { + pub(crate) remove: Vec, + pub(crate) high: String, + pub(crate) medium: String, + pub(crate) low: String, +} + pub(crate) async fn get(gh: &GithubClient, repo: &str) -> Result, ConfigurationError> { if let Some(config) = get_cached_config(repo) { log::trace!("returning config for {} from cache", repo); @@ -310,6 +319,7 @@ mod tests { notify_zulip: None, github_releases: None, review_submitted: None, + triage: None, } ); } diff --git a/src/handlers.rs b/src/handlers.rs index 1b58533be..8ebf0c4f4 100644 --- a/src/handlers.rs +++ b/src/handlers.rs @@ -38,6 +38,7 @@ mod relabel; mod review_submitted; mod rustc_commits; mod shortcut; +mod triage; pub async fn handle(ctx: &Context, event: &Event) -> Vec { let config = config::get(&ctx.github, &event.repo_name()).await; @@ -242,6 +243,7 @@ command_handlers! { major_change: Second, shortcut: Shortcut, close: Close, + triage: Triage, } pub struct Context { diff --git a/src/handlers/triage.rs b/src/handlers/triage.rs new file mode 100644 index 000000000..264b93312 --- /dev/null +++ b/src/handlers/triage.rs @@ -0,0 +1,48 @@ +//! Triage command +//! +//! Removes I-nominated tag and adds priority label. + +use crate::{ + config::TriageConfig, + github::{self, Event}, + handlers::Context, +}; +use parser::command::triage::{Priority, TriageCommand}; + +pub(super) async fn handle_command( + ctx: &Context, + config: &TriageConfig, + event: &Event, + cmd: TriageCommand, +) -> anyhow::Result<()> { + let event = if let Event::IssueComment(e) = event { + e + } else { + // not interested in other events + return Ok(()); + }; + + let is_team_member = + if let Err(_) | Ok(false) = event.comment.user.is_team_member(&ctx.github).await { + false + } else { + true + }; + if !is_team_member { + anyhow::bail!("Cannot use triage command as non-team-member"); + } + + let mut labels = event.issue.labels().to_owned(); + let add = match cmd.priority { + Priority::High => &config.high, + Priority::Medium => &config.medium, + Priority::Low => &config.low, + }; + labels.push(github::Label { name: add.clone() }); + labels.retain(|label| !config.remove.contains(&label.name)); + if &labels[..] != event.issue.labels() { + event.issue.set_labels(&ctx.github, labels).await?; + } + + Ok(()) +} From d854bf11ec7eaf648c0487f8a5f8428518754d47 Mon Sep 17 00:00:00 2001 From: kellda <59569234+kellda@users.noreply.github.com> Date: Fri, 10 Sep 2021 13:24:36 +0000 Subject: [PATCH 2/2] Add critical priority --- parser/src/command/triage.rs | 9 +++++++-- src/config.rs | 1 + src/handlers/triage.rs | 1 + 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/parser/src/command/triage.rs b/parser/src/command/triage.rs index d0175e9e9..f3c44f6ab 100644 --- a/parser/src/command/triage.rs +++ b/parser/src/command/triage.rs @@ -14,9 +14,10 @@ use std::fmt; #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum Priority { + Critical, High, - Low, Medium, + Low, } #[derive(PartialEq, Eq, Debug)] @@ -35,7 +36,7 @@ impl std::error::Error for ParseError {} impl fmt::Display for ParseError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { - ParseError::ExpectedPriority => write!(f, "expected priority (high, medium, low)"), + ParseError::ExpectedPriority => write!(f, "expected priority (critical, high, medium, low)"), ParseError::ExpectedEnd => write!(f, "expected end of command"), } } @@ -47,6 +48,10 @@ impl TriageCommand { if let Some(Token::Word("triage")) = toks.peek_token()? { toks.next_token()?; let priority = match toks.peek_token()? { + Some(Token::Word("critical")) | Some(Token::Word("P-critical")) => { + toks.next_token()?; + Priority::Critical + } Some(Token::Word("high")) | Some(Token::Word("P-high")) => { toks.next_token()?; Priority::High diff --git a/src/config.rs b/src/config.rs index 51d762d28..474a1769f 100644 --- a/src/config.rs +++ b/src/config.rs @@ -162,6 +162,7 @@ pub(crate) struct ReviewSubmittedConfig { #[derive(PartialEq, Eq, Debug, serde::Deserialize)] pub(crate) struct TriageConfig { pub(crate) remove: Vec, + pub(crate) critical: String, pub(crate) high: String, pub(crate) medium: String, pub(crate) low: String, diff --git a/src/handlers/triage.rs b/src/handlers/triage.rs index 264b93312..01f85fa86 100644 --- a/src/handlers/triage.rs +++ b/src/handlers/triage.rs @@ -34,6 +34,7 @@ pub(super) async fn handle_command( let mut labels = event.issue.labels().to_owned(); let add = match cmd.priority { + Priority::Critical => &config.critical, Priority::High => &config.high, Priority::Medium => &config.medium, Priority::Low => &config.low,