1
+ use crate :: db:: issue_data:: IssueData ;
1
2
use crate :: {
2
3
config:: AutolabelConfig ,
3
4
github:: { IssuesAction , IssuesEvent , Label } ,
@@ -6,6 +7,15 @@ use crate::{
6
7
use anyhow:: Context as _;
7
8
use tracing as log;
8
9
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 , serde:: Deserialize , serde:: Serialize ) ]
15
+ struct AutolabelState {
16
+ new_pr_labels_applied : bool ,
17
+ }
18
+
9
19
pub ( super ) struct AutolabelInput {
10
20
add : Vec < Label > ,
11
21
remove : Vec < Label > ,
@@ -27,6 +37,12 @@ pub(super) async fn parse_input(
27
37
// remove. Not much can be done about that currently; the before/after on
28
38
// synchronize may be straddling a rebase, which will break diff generation.
29
39
if event. action == IssuesAction :: Opened || event. action == IssuesAction :: Synchronize {
40
+ let mut db = ctx. db . get ( ) . await ;
41
+ let mut state: IssueData < ' _ , AutolabelState > =
42
+ IssueData :: load ( & mut db, & event. issue , AUTOLABEL_KEY )
43
+ . await
44
+ . map_err ( |e| e. to_string ( ) ) ?;
45
+
30
46
let files = event
31
47
. issue
32
48
. diff ( & ctx. github )
@@ -69,11 +85,18 @@ pub(super) async fn parse_input(
69
85
name : label. to_owned ( ) ,
70
86
} ) ;
71
87
}
72
- if cfg. new_pr && event. action == IssuesAction :: Opened {
73
- autolabels. push ( Label {
74
- name : label. to_owned ( ) ,
75
- } ) ;
76
- }
88
+ }
89
+
90
+ // Newly opened non-draft PRs or PRs that were opened as draft and that were marked as
91
+ // "ready for review" for the first time are treated as "new PRs".
92
+ let treat_as_new_pr = ( event. action == IssuesAction :: Opened && !event. issue . draft )
93
+ || ( event. action == IssuesAction :: ReadyForReview
94
+ && !state. data . new_pr_labels_applied ) ;
95
+ if cfg. new_pr && treat_as_new_pr {
96
+ autolabels. push ( Label {
97
+ name : label. to_owned ( ) ,
98
+ } ) ;
99
+ state. data . new_pr_labels_applied = true ;
77
100
}
78
101
79
102
if event. issue . pull_request . is_none ( )
@@ -86,6 +109,8 @@ pub(super) async fn parse_input(
86
109
}
87
110
}
88
111
112
+ state. save ( ) . await . map_err ( |e| e. to_string ( ) ) ?;
113
+
89
114
if !autolabels. is_empty ( ) {
90
115
return Ok ( Some ( AutolabelInput {
91
116
add : autolabels,
0 commit comments