1
- use crate :: db:: issue_data:: IssueData ;
2
1
use crate :: {
3
2
config:: AutolabelConfig ,
4
3
github:: { IssuesAction , IssuesEvent , Label } ,
@@ -7,16 +6,6 @@ use crate::{
7
6
use anyhow:: Context as _;
8
7
use tracing as log;
9
8
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
-
20
9
pub ( super ) struct AutolabelInput {
21
10
add : Vec < Label > ,
22
11
remove : Vec < Label > ,
@@ -37,25 +26,35 @@ pub(super) async fn parse_input(
37
26
// FIXME: This will re-apply labels after a push that the user had tried to
38
27
// remove. Not much can be done about that currently; the before/after on
39
28
// synchronize may be straddling a rebase, which will break diff generation.
40
- if matches ! (
29
+ let can_trigger_files = matches ! (
41
30
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 )
47
47
. 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
+ } ;
49
55
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 ( ) ;
58
56
let mut autolabels = Vec :: new ( ) ;
57
+ let mut to_remove = Vec :: new ( ) ;
59
58
60
59
' outer: for ( label, cfg) in config. labels . iter ( ) {
61
60
let exclude_patterns: Vec < glob:: Pattern > = cfg
@@ -96,17 +95,28 @@ pub(super) async fn parse_input(
96
95
}
97
96
98
97
// 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 ) {
106
105
autolabels. push ( Label {
107
106
name : label. to_owned ( ) ,
108
107
} ) ;
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
+ } ) ;
110
120
}
111
121
} else {
112
122
if cfg. new_issue && event. action == IssuesAction :: Opened {
@@ -117,12 +127,10 @@ pub(super) async fn parse_input(
117
127
}
118
128
}
119
129
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 ( ) {
123
131
return Ok ( Some ( AutolabelInput {
124
132
add : autolabels,
125
- remove : vec ! [ ] ,
133
+ remove : to_remove ,
126
134
} ) ) ;
127
135
}
128
136
}
0 commit comments