1- use crate :: db:: issue_data:: IssueData ;
21use crate :: {
32 config:: AutolabelConfig ,
43 github:: { IssuesAction , IssuesEvent , Label } ,
@@ -7,16 +6,6 @@ use crate::{
76use anyhow:: Context as _;
87use tracing as log;
98
10- /// Key for the state in the database
11- const AUTOLABEL_KEY : & str = "autolabel" ;
12-
13- /// State stored in the database
14- #[ derive( Debug , Default , PartialEq , Clone , serde:: Deserialize , serde:: Serialize ) ]
15- struct AutolabelState {
16- /// If true, then `autolabel.new_pr` labels have already been applied to this PR.
17- new_pr_labels_applied : bool ,
18- }
19-
209pub ( super ) struct AutolabelInput {
2110 add : Vec < Label > ,
2211 remove : Vec < Label > ,
@@ -37,25 +26,35 @@ pub(super) async fn parse_input(
3726 // FIXME: This will re-apply labels after a push that the user had tried to
3827 // remove. Not much can be done about that currently; the before/after on
3928 // synchronize may be straddling a rebase, which will break diff generation.
40- if matches ! (
29+ let can_trigger_files = matches ! (
4130 event. action,
42- IssuesAction :: Opened | IssuesAction :: Synchronize | IssuesAction :: ReadyForReview
43- ) {
44- let mut db = ctx. db . get ( ) . await ;
45- let mut state: IssueData < ' _ , AutolabelState > =
46- IssueData :: load ( & mut db, & event. issue , AUTOLABEL_KEY )
31+ IssuesAction :: Opened | IssuesAction :: Synchronize
32+ ) ;
33+
34+ if can_trigger_files
35+ || matches ! (
36+ event. action,
37+ IssuesAction :: Closed
38+ | IssuesAction :: Reopened
39+ | IssuesAction :: ReadyForReview
40+ | IssuesAction :: ConvertedToDraft
41+ )
42+ {
43+ let files = if can_trigger_files {
44+ event
45+ . issue
46+ . diff ( & ctx. github )
4747 . await
48- . map_err ( |e| e. to_string ( ) ) ?;
48+ . map_err ( |e| {
49+ log:: error!( "failed to fetch diff: {:?}" , e) ;
50+ } )
51+ . unwrap_or_default ( )
52+ } else {
53+ Default :: default ( )
54+ } ;
4955
50- let files = event
51- . issue
52- . diff ( & ctx. github )
53- . await
54- . map_err ( |e| {
55- log:: error!( "failed to fetch diff: {:?}" , e) ;
56- } )
57- . unwrap_or_default ( ) ;
5856 let mut autolabels = Vec :: new ( ) ;
57+ let mut to_remove = Vec :: new ( ) ;
5958
6059 ' outer: for ( label, cfg) in config. labels . iter ( ) {
6160 let exclude_patterns: Vec < glob:: Pattern > = cfg
@@ -96,17 +95,28 @@ pub(super) async fn parse_input(
9695 }
9796
9897 // Treat the following situations as a "new PR":
99- // 1) New PRs opened as non- draft
100- // 2) PRs opened as draft that are marked as "ready for review" for the first time.
101- let is_new_non_draft_pr =
102- event. action == IssuesAction :: Opened && !event . issue . draft ;
103- let is_first_time_ready_for_review = event . action == IssuesAction :: ReadyForReview
104- && !state . data . new_pr_labels_applied ;
105- if cfg. new_pr && ( is_new_non_draft_pr || is_first_time_ready_for_review ) {
98+ // 1) PRs that were (re) opened and are not draft
99+ // 2) PRs that have been converted from a draft to being "ready for review"
100+ let is_opened_non_draft =
101+ matches ! ( event. action, IssuesAction :: Opened | IssuesAction :: Reopened )
102+ && !event . issue . draft ;
103+ let is_ready_for_review = event . action == IssuesAction :: ReadyForReview ;
104+ if cfg. new_pr && ( is_opened_non_draft || is_ready_for_review ) {
106105 autolabels. push ( Label {
107106 name : label. to_owned ( ) ,
108107 } ) ;
109- state. data . new_pr_labels_applied = true ;
108+ }
109+
110+ // If a PR is converted to draft or closed, remove all the "new PR" labels
111+ if cfg. new_pr
112+ && matches ! (
113+ event. action,
114+ IssuesAction :: ConvertedToDraft | IssuesAction :: Closed
115+ )
116+ {
117+ to_remove. push ( Label {
118+ name : label. to_owned ( ) ,
119+ } ) ;
110120 }
111121 } else {
112122 if cfg. new_issue && event. action == IssuesAction :: Opened {
@@ -117,12 +127,10 @@ pub(super) async fn parse_input(
117127 }
118128 }
119129
120- state. save ( ) . await . map_err ( |e| e. to_string ( ) ) ?;
121-
122- if !autolabels. is_empty ( ) {
130+ if !autolabels. is_empty ( ) || !to_remove. is_empty ( ) {
123131 return Ok ( Some ( AutolabelInput {
124132 add : autolabels,
125- remove : vec ! [ ] ,
133+ remove : to_remove ,
126134 } ) ) ;
127135 }
128136 }
0 commit comments