Skip to content

Commit d7ae8c1

Browse files
authored
Comment on issues when @rustbot label is given an invalid label (#1610)
Previously, the label was just silently ignored, along with all other labels in the same command. This tells the user what went wrong, and also adds all valid labels
1 parent f23308a commit d7ae8c1

File tree

2 files changed

+55
-10
lines changed

2 files changed

+55
-10
lines changed

src/github.rs

Lines changed: 43 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -366,17 +366,36 @@ impl IssueRepository {
366366
)
367367
}
368368

369-
async fn has_label(&self, client: &GithubClient, label: &str) -> bool {
369+
async fn has_label(&self, client: &GithubClient, label: &str) -> anyhow::Result<bool> {
370370
#[allow(clippy::redundant_pattern_matching)]
371371
let url = format!("{}/labels/{}", self.url(), label);
372-
match client.send_req(client.get(&url)).await {
373-
Ok(_) => true,
374-
// XXX: Error handling if the request failed for reasons beyond 'label didn't exist'
375-
Err(_) => false,
372+
match client._send_req(client.get(&url)).await {
373+
Ok((_, _)) => Ok(true),
374+
Err(e) => {
375+
if e.downcast_ref::<reqwest::Error>().map_or(false, |e| e.status() == Some(StatusCode::NOT_FOUND)) {
376+
Ok(false)
377+
} else {
378+
Err(e)
379+
}
380+
}
376381
}
377382
}
378383
}
379384

385+
#[derive(Debug)]
386+
pub(crate) struct UnknownLabels {
387+
labels: Vec<String>,
388+
}
389+
390+
// NOTE: This is used to post the Github comment; make sure it's valid markdown.
391+
impl fmt::Display for UnknownLabels {
392+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
393+
write!(f, "Unknown labels: {}", &self.labels.join(", "))
394+
}
395+
}
396+
397+
impl std::error::Error for UnknownLabels {}
398+
380399
impl Issue {
381400
pub fn to_zulip_github_reference(&self) -> ZulipGitHubReference {
382401
ZulipGitHubReference {
@@ -519,18 +538,27 @@ impl Issue {
519538
return Ok(());
520539
}
521540

522-
for label in &labels {
523-
if !self.repository().has_label(client, &label).await {
524-
anyhow::bail!("Label {} does not exist in {}", label, self.global_id());
541+
let mut unknown_labels = vec![];
542+
let mut known_labels = vec![];
543+
for label in labels {
544+
if !self.repository().has_label(client, &label).await? {
545+
unknown_labels.push(label);
546+
} else {
547+
known_labels.push(label);
525548
}
526549
}
527550

551+
if !unknown_labels.is_empty() {
552+
return Err(UnknownLabels { labels: unknown_labels }.into());
553+
}
554+
528555
#[derive(serde::Serialize)]
529556
struct LabelsReq {
530557
labels: Vec<String>,
531558
}
559+
532560
client
533-
._send_req(client.post(&url).json(&LabelsReq { labels }))
561+
._send_req(client.post(&url).json(&LabelsReq { labels: known_labels }))
534562
.await
535563
.context("failed to add labels")?;
536564

@@ -1430,6 +1458,12 @@ pub trait IssuesQuery {
14301458
mod tests {
14311459
use super::*;
14321460

1461+
#[test]
1462+
fn display_labels() {
1463+
let x = UnknownLabels { labels: vec!["A-bootstrap".into(), "xxx".into()] };
1464+
assert_eq!(x.to_string(), "Unknown labels: A-bootstrap, xxx");
1465+
}
1466+
14331467
#[test]
14341468
fn extract_one_file() {
14351469
let input = r##"\

src/handlers/autolabel.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,18 @@ pub(super) async fn handle_input(
125125
event: &IssuesEvent,
126126
input: AutolabelInput,
127127
) -> anyhow::Result<()> {
128-
event.issue.add_labels(&ctx.github, input.add).await?;
128+
match event.issue.add_labels(&ctx.github, input.add).await {
129+
Ok(()) => {}
130+
Err(e) => {
131+
use crate::github::UnknownLabels;
132+
if let Some(err @ UnknownLabels { .. }) = e.downcast_ref() {
133+
event.issue.post_comment(&ctx.github, &err.to_string()).await.context("failed to post missing label comment")?;
134+
return Ok(());
135+
}
136+
return Err(e);
137+
}
138+
}
139+
129140
for label in input.remove {
130141
event
131142
.issue

0 commit comments

Comments
 (0)