Skip to content
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 18 additions & 27 deletions src/handlers/autolabel.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use crate::db::issue_data::IssueData;
use crate::{
config::AutolabelConfig,
github::{IssuesAction, IssuesEvent, Label},
Expand All @@ -7,16 +6,6 @@ use crate::{
use anyhow::Context as _;
use tracing as log;

/// Key for the state in the database
const AUTOLABEL_KEY: &str = "autolabel";

/// State stored in the database
#[derive(Debug, Default, PartialEq, Clone, serde::Deserialize, serde::Serialize)]
struct AutolabelState {
/// If true, then `autolabel.new_pr` labels have already been applied to this PR.
new_pr_labels_applied: bool,
}

pub(super) struct AutolabelInput {
add: Vec<Label>,
remove: Vec<Label>,
Expand All @@ -39,14 +28,11 @@ pub(super) async fn parse_input(
// synchronize may be straddling a rebase, which will break diff generation.
if matches!(
event.action,
IssuesAction::Opened | IssuesAction::Synchronize | IssuesAction::ReadyForReview
IssuesAction::Opened
| IssuesAction::Synchronize
| IssuesAction::ReadyForReview
| IssuesAction::ConvertedToDraft
) {
let mut db = ctx.db.get().await;
let mut state: IssueData<'_, AutolabelState> =
IssueData::load(&mut db, &event.issue, AUTOLABEL_KEY)
.await
.map_err(|e| e.to_string())?;

let files = event
.issue
.diff(&ctx.github)
Expand All @@ -55,7 +41,9 @@ pub(super) async fn parse_input(
log::error!("failed to fetch diff: {:?}", e);
})
.unwrap_or_default();

let mut autolabels = Vec::new();
let mut to_remove = Vec::new();

'outer: for (label, cfg) in config.labels.iter() {
let exclude_patterns: Vec<glob::Pattern> = cfg
Expand Down Expand Up @@ -97,16 +85,21 @@ pub(super) async fn parse_input(

// Treat the following situations as a "new PR":
// 1) New PRs opened as non-draft
// 2) PRs opened as draft that are marked as "ready for review" for the first time.
// 2) PRs opened as draft that are marked as "ready for review".
let is_new_non_draft_pr =
event.action == IssuesAction::Opened && !event.issue.draft;
let is_first_time_ready_for_review = event.action == IssuesAction::ReadyForReview
&& !state.data.new_pr_labels_applied;
if cfg.new_pr && (is_new_non_draft_pr || is_first_time_ready_for_review) {
let is_ready_for_review = event.action == IssuesAction::ReadyForReview;
if cfg.new_pr && (is_new_non_draft_pr || is_ready_for_review) {
autolabels.push(Label {
name: label.to_owned(),
});
state.data.new_pr_labels_applied = true;
}

// If a PR is converted to draft remove all the "new PR" labels
if cfg.new_pr && event.action == IssuesAction::ConvertedToDraft {
to_remove.push(Label {
name: label.to_owned(),
});
}
} else {
if cfg.new_issue && event.action == IssuesAction::Opened {
Expand All @@ -117,12 +110,10 @@ pub(super) async fn parse_input(
}
}

state.save().await.map_err(|e| e.to_string())?;

if !autolabels.is_empty() {
if !autolabels.is_empty() || !to_remove.is_empty() {
return Ok(Some(AutolabelInput {
add: autolabels,
remove: vec![],
remove: to_remove,
}));
}
}
Expand Down