1+ use crate :: db:: issue_data:: IssueData ;
12use crate :: {
23 config:: AutolabelConfig ,
34 github:: { IssuesAction , IssuesEvent , Label } ,
@@ -6,6 +7,16 @@ use crate::{
67use anyhow:: Context as _;
78use tracing as log;
89
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+ /// If true, then `autolabel.new_pr` labels have already been applied to this PR.
17+ new_pr_labels_applied : bool ,
18+ }
19+
920pub ( super ) struct AutolabelInput {
1021 add : Vec < Label > ,
1122 remove : Vec < Label > ,
@@ -27,6 +38,12 @@ pub(super) async fn parse_input(
2738 // remove. Not much can be done about that currently; the before/after on
2839 // synchronize may be straddling a rebase, which will break diff generation.
2940 if event. action == IssuesAction :: Opened || event. action == IssuesAction :: Synchronize {
41+ let mut db = ctx. db . get ( ) . await ;
42+ let mut state: IssueData < ' _ , AutolabelState > =
43+ IssueData :: load ( & mut db, & event. issue , AUTOLABEL_KEY )
44+ . await
45+ . map_err ( |e| e. to_string ( ) ) ?;
46+
3047 let files = event
3148 . issue
3249 . diff ( & ctx. github )
@@ -69,11 +86,19 @@ pub(super) async fn parse_input(
6986 name : label. to_owned ( ) ,
7087 } ) ;
7188 }
72- if cfg. new_pr && event. action == IssuesAction :: Opened {
73- autolabels. push ( Label {
74- name : label. to_owned ( ) ,
75- } ) ;
76- }
89+ }
90+
91+ // Treat the following situations as a "new PR":
92+ // 1) New PRs opened as non-draft
93+ // 2) PRs opened as draft that are marked as "ready for review" for the first time.
94+ let is_new_non_draft_pr = event. action == IssuesAction :: Opened && !event. issue . draft ;
95+ let is_first_time_ready_for_review =
96+ event. action == IssuesAction :: ReadyForReview && !state. data . new_pr_labels_applied ;
97+ if cfg. new_pr && ( is_new_non_draft_pr || is_first_time_ready_for_review) {
98+ autolabels. push ( Label {
99+ name : label. to_owned ( ) ,
100+ } ) ;
101+ state. data . new_pr_labels_applied = true ;
77102 }
78103
79104 if event. issue . pull_request . is_none ( )
@@ -86,6 +111,8 @@ pub(super) async fn parse_input(
86111 }
87112 }
88113
114+ state. save ( ) . await . map_err ( |e| e. to_string ( ) ) ?;
115+
89116 if !autolabels. is_empty ( ) {
90117 return Ok ( Some ( AutolabelInput {
91118 add : autolabels,
0 commit comments