@@ -3,18 +3,35 @@ use anyhow::bail;
3
3
use super :: Context ;
4
4
use crate :: {
5
5
config:: Config ,
6
- github:: { Event , IssuesAction } ,
6
+ db:: issue_data:: IssueData ,
7
+ github:: { Event , IssuesAction , IssuesEvent , ReportedContentClassifiers } ,
7
8
} ;
8
9
9
10
mod modified_submodule;
10
11
mod non_default_branch;
11
12
13
+ /// Key for the state in the database
14
+ const CHECK_COMMITS_WARNINGS_KEY : & str = "check-commits-warnings" ;
15
+
16
+ /// State stored in the database
17
+ #[ derive( Debug , Default , serde:: Deserialize , serde:: Serialize ) ]
18
+ struct CheckCommitsWarningsState {
19
+ /// List of the last warnings in the most recent comment.
20
+ last_warnings : Vec < String > ,
21
+ /// ID of the most recent warning comment.
22
+ last_warned_comment : Option < String > ,
23
+ }
24
+
12
25
pub ( super ) async fn handle ( ctx : & Context , event : & Event , config : & Config ) -> anyhow:: Result < ( ) > {
13
26
let Event :: Issue ( event) = event else {
14
27
return Ok ( ( ) ) ;
15
28
} ;
16
29
17
- if !matches ! ( event. action, IssuesAction :: Opened ) || !event. issue . is_pr ( ) {
30
+ if !matches ! (
31
+ event. action,
32
+ IssuesAction :: Opened | IssuesAction :: Synchronize
33
+ ) || !event. issue . is_pr ( )
34
+ {
18
35
return Ok ( ( ) ) ;
19
36
}
20
37
@@ -27,6 +44,7 @@ pub(super) async fn handle(ctx: &Context, event: &Event, config: &Config) -> any
27
44
28
45
let mut warnings = Vec :: new ( ) ;
29
46
47
+ // Compute the warnings
30
48
if let Some ( assign_config) = & config. assign {
31
49
// For legacy reasons the non-default-branch and modifies-submodule warnings
32
50
// are behind the `[assign]` config.
@@ -40,14 +58,65 @@ pub(super) async fn handle(ctx: &Context, event: &Event, config: &Config) -> any
40
58
warnings. extend ( modified_submodule:: modifies_submodule ( diff) ) ;
41
59
}
42
60
43
- if !warnings. is_empty ( ) {
61
+ handle_warnings ( ctx, event, warnings) . await
62
+ }
63
+
64
+ // Add, hide or hide&add a comment with the warnings.
65
+ async fn handle_warnings (
66
+ ctx : & Context ,
67
+ event : & IssuesEvent ,
68
+ warnings : Vec < String > ,
69
+ ) -> anyhow:: Result < ( ) > {
70
+ // Get the state of the warnings for this PR in the database.
71
+ let mut db = ctx. db . get ( ) . await ;
72
+ let mut state: IssueData < ' _ , CheckCommitsWarningsState > =
73
+ IssueData :: load ( & mut db, & event. issue , CHECK_COMMITS_WARNINGS_KEY ) . await ?;
74
+
75
+ // We only post a new comment when we haven't posted one with the same warnings before.
76
+ if !warnings. is_empty ( ) && state. data . last_warnings != warnings {
77
+ // New set of warnings, let's post them.
78
+
79
+ // Hide a previous warnings comment if there was one before printing the new ones.
80
+ if let Some ( last_warned_comment_id) = state. data . last_warned_comment {
81
+ event
82
+ . issue
83
+ . hide_comment (
84
+ & ctx. github ,
85
+ & last_warned_comment_id,
86
+ ReportedContentClassifiers :: Resolved ,
87
+ )
88
+ . await ?;
89
+ }
90
+
91
+ // Format the warnings for user consumption on Github
44
92
let warnings: Vec < _ > = warnings
45
93
. iter ( )
46
94
. map ( |warning| format ! ( "* {warning}" ) )
47
95
. collect ( ) ;
48
96
let warning = format ! ( ":warning: **Warning** :warning:\n \n {}" , warnings. join( "\n " ) ) ;
49
- event. issue . post_comment ( & ctx. github , & warning) . await ?;
50
- } ;
97
+ let comment = event. issue . post_comment ( & ctx. github , & warning) . await ?;
98
+
99
+ // Save new state in the database
100
+ state. data . last_warnings = warnings;
101
+ state. data . last_warned_comment = Some ( comment. node_id ) ;
102
+ state. save ( ) . await ?;
103
+ } else if warnings. is_empty ( ) {
104
+ // No warnings to be shown, let's resolve a previous warnings comment, if there was one.
105
+ if let Some ( last_warned_comment_id) = state. data . last_warned_comment {
106
+ event
107
+ . issue
108
+ . hide_comment (
109
+ & ctx. github ,
110
+ & last_warned_comment_id,
111
+ ReportedContentClassifiers :: Resolved ,
112
+ )
113
+ . await ?;
114
+
115
+ state. data . last_warnings = Vec :: new ( ) ;
116
+ state. data . last_warned_comment = None ;
117
+ state. save ( ) . await ?;
118
+ }
119
+ }
51
120
52
121
Ok ( ( ) )
53
122
}
0 commit comments