Skip to content

Commit e747558

Browse files
committed
Improvements to the assign-priority command
This patch adds a few small changes to the issue prioritization triagebot Zulip command: - It is now accepted the shortcut "prio" - The issue number is optional. If omitted it is searched in Zulip topic title - When we edit the Zulip topic, we ensure we do not set the same topic (the Zulip API returns an error) Examples: ``` triagebot assign-priority high 123456 triagebot prio medium 123456 triagebot prio high ``` This will change the syntax of the command so I will update the documentation.
1 parent a5bbaa9 commit e747558

3 files changed

Lines changed: 69 additions & 10 deletions

File tree

‎src/zulip.rs‎

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,18 @@ use axum::extract::rejection::JsonRejection;
3030
use axum::response::IntoResponse;
3131
use chrono::{DateTime, Duration, Utc};
3232
use itertools::Itertools;
33+
use regex::Regex;
3334
use rust_team_data::v1::{TeamKind, TeamMember};
3435
use secrecy::{ExposeSecret, SecretString};
3536
use std::cmp::{Ordering, Reverse};
3637
use std::collections::{HashMap, HashSet};
3738
use std::fmt::Write as _;
38-
use std::sync::Arc;
39+
use std::sync::{Arc, LazyLock};
3940
use subtle::ConstantTimeEq;
4041
use tracing::log;
4142

43+
static RE_ISSUE_NUM: LazyLock<Regex> = LazyLock::new(|| Regex::new(r"#[0-9]*").unwrap());
44+
4245
fn get_text_backport_approved(
4346
channel: &BackportChannelArgs,
4447
verb: &BackportVerbArgs,
@@ -71,6 +74,7 @@ pub struct Request {
7174
token: SecretString,
7275
}
7376

77+
// Zulip webhook payload: https://rust-lang.zulipchat.com/api/outgoing-webhook-payload
7478
#[derive(Clone, Debug, serde::Deserialize)]
7579
struct Message {
7680
id: u64,
@@ -396,7 +400,7 @@ async fn handle_command<'a>(
396400
}
397401
}
398402
Err(err) => {
399-
log::error!("Could not assign priority to #{}: {:?}", issue_num, err);
403+
log::error!("Could not assign priority to #{:?}: {:?}", issue_num, err);
400404
ctx.zulip.add_reaction(message_data.id, "scream").await?;
401405
}
402406
};
@@ -445,7 +449,7 @@ async fn accept_decline_backport(
445449
let mut pr_num = pr_num;
446450
let mut channel = channel.clone();
447451

448-
// Parse the stream subjetc if the channel or the pr num are not provided
452+
// Parse the stream subject if the channel or the pr num are not provided
449453
if pr_num.is_none() || channel.is_none() {
450454
let (maybe_pr_num, maybe_channel) = subject
451455
.rsplit_once(':')
@@ -559,9 +563,9 @@ async fn accept_decline_backport(
559563
async fn assign_issue_prio(
560564
ctx: &Context,
561565
message_data: &Message,
562-
issue_num: PullRequestNumber,
566+
issue_num: Option<PullRequestNumber>,
563567
prio: IssuePrio,
564-
) -> anyhow::Result<Option<String>> {
568+
) -> anyhow::Result<()> {
565569
let message = message_data.clone();
566570
let stream_id = message.stream_id.unwrap();
567571
let subject = message.subject.unwrap();
@@ -579,6 +583,23 @@ async fn assign_issue_prio(
579583
parent: None,
580584
};
581585

586+
// Parse the Zulip topic subject if an issue num was not provided
587+
// Hopefully it is something like "#123456 Some text" or "✔ #123456 Some text"
588+
let mut issue_num: Option<u64> = issue_num;
589+
if issue_num.is_none() {
590+
issue_num = Some(
591+
RE_ISSUE_NUM
592+
.find(&subject)
593+
.expect("Cannot parse issue num")
594+
.as_str()
595+
.strip_prefix('#')
596+
.expect("Cannot parse issue num")
597+
.parse::<u64>()
598+
.expect("Cannot parse issue num"),
599+
);
600+
}
601+
let issue_num = issue_num.context("No issue number to apply to")?;
602+
582603
// Ensure this is an issue and not a pull request
583604
let issue = repository
584605
.get_issue(&ctx.github, issue_num)
@@ -615,7 +636,7 @@ async fn assign_issue_prio(
615636

616637
// if just removing priority, nothing else to do
617638
if prio == IssuePrio::None {
618-
return Ok(None);
639+
return Ok(());
619640
}
620641

621642
// post a comment on GitHub
@@ -640,7 +661,7 @@ async fn assign_issue_prio(
640661
.await
641662
.context(format!("failed to add labels to issue #{}", issue_num))?;
642663

643-
Ok(None)
664+
Ok(())
644665
}
645666

646667
/// Unlock a specific issue in our managed repos.

‎src/zulip/client.rs‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,11 @@ impl ZulipClient {
221221
}
222222

223223
let topic = format_resolved_topic(message_topic);
224+
// Zulip returns a BAD_REQUEST error if attempting to set the same title for a topic
225+
// so in this case just return
226+
if topic == message_topic {
227+
return Ok(());
228+
}
224229

225230
let resp = self
226231
.make_request(Method::PATCH, &format!("messages/{message_id}"))

‎src/zulip/commands.rs‎

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -173,11 +173,12 @@ pub enum StreamCommand {
173173
#[clap(subcommand)]
174174
Lookup(LookupCmd),
175175
/// Label assignment: add one of `P-{low,medium,high,critical}` and remove `I-prioritize`
176+
#[clap(alias = "prio")]
176177
AssignPriority {
177-
/// Issue target of the prioritization
178-
issue_num: PullRequestNumber,
179178
/// Issue priority. Allowed: "low", "medium", "high", "critical", "none" (to just remove the prioritization)
180179
prio: IssuePrio,
180+
/// Issue target of the prioritization
181+
issue_num: Option<PullRequestNumber>,
181182
},
182183
/// Unlock a specific GitHub issue or pull-request.
183184
Unlock {
@@ -198,7 +199,7 @@ pub enum StreamCommand {
198199
/// Version of the crate to yank
199200
version: semver::Version,
200201
},
201-
/// Unynk a specific crate version from crates.io.
202+
/// Unyank a specific crate version from crates.io.
202203
/// Can only be performed by members of teams that own the crate.
203204
Unyank {
204205
/// Crate to unyank.
@@ -519,4 +520,36 @@ mod tests {
519520
fn parse_stream(input: &[&str]) -> StreamCommand {
520521
parse_cli::<StreamCommand, _>(input.into_iter().copied()).unwrap()
521522
}
523+
524+
#[test]
525+
fn parse_assign_prio_command() {
526+
assert_eq!(
527+
parse_stream(&["assign-priority", "medium", "123456"]),
528+
StreamCommand::AssignPriority {
529+
prio: IssuePrio::Medium,
530+
issue_num: Some(123456)
531+
}
532+
);
533+
assert_eq!(
534+
parse_stream(&["assign-priority", "none"]),
535+
StreamCommand::AssignPriority {
536+
prio: IssuePrio::None,
537+
issue_num: None
538+
}
539+
);
540+
assert_eq!(
541+
parse_stream(&["prio", "medium", "123456"]),
542+
StreamCommand::AssignPriority {
543+
prio: IssuePrio::Medium,
544+
issue_num: Some(123456)
545+
}
546+
);
547+
assert_eq!(
548+
parse_stream(&["prio", "medium"]),
549+
StreamCommand::AssignPriority {
550+
prio: IssuePrio::Medium,
551+
issue_num: None
552+
}
553+
);
554+
}
522555
}

0 commit comments

Comments
 (0)