@@ -21,11 +21,14 @@ mod no_merges;
2121mod non_default_branch;
2222
2323/// Key for the state in the database
24- const CHECK_COMMITS_WARNINGS_KEY : & str = "check-commits-warnings" ;
24+ const CHECK_COMMITS_KEY : & str = "check-commits-warnings" ;
2525
2626/// State stored in the database
2727#[ derive( Debug , Default , serde:: Deserialize , serde:: Serialize , Clone , PartialEq ) ]
28- struct CheckCommitsWarningsState {
28+ struct CheckCommitsState {
29+ /// List of the last errors (comment body, comment node-id).
30+ #[ serde( default ) ]
31+ last_errors : Vec < ( String , String ) > ,
2932 /// List of the last warnings in the most recent comment.
3033 last_warnings : Vec < String > ,
3134 /// ID of the most recent warning comment.
@@ -61,6 +64,7 @@ pub(super) async fn handle(ctx: &Context, event: &Event, config: &Config) -> any
6164 let commits = event. issue . commits ( & ctx. github ) . await ?;
6265 let diff = & compare. files ;
6366
67+ let mut errors = Vec :: new ( ) ;
6468 let mut warnings = Vec :: new ( ) ;
6569 let mut labels = Vec :: new ( ) ;
6670
@@ -108,20 +112,44 @@ pub(super) async fn handle(ctx: &Context, event: &Event, config: &Config) -> any
108112 }
109113 }
110114
111- handle_warnings_and_labels ( ctx, event, warnings, labels) . await
115+ handle_new_state ( ctx, event, errors , warnings, labels) . await
112116}
113117
114118// Add, hide or hide&add a comment with the warnings.
115- async fn handle_warnings_and_labels (
119+ async fn handle_new_state (
116120 ctx : & Context ,
117121 event : & IssuesEvent ,
122+ errors : Vec < String > ,
118123 warnings : Vec < String > ,
119124 labels : Vec < String > ,
120125) -> anyhow:: Result < ( ) > {
121126 // Get the state of the warnings for this PR in the database.
122127 let mut db = ctx. db . get ( ) . await ;
123- let mut state: IssueData < ' _ , CheckCommitsWarningsState > =
124- IssueData :: load ( & mut db, & event. issue , CHECK_COMMITS_WARNINGS_KEY ) . await ?;
128+ let mut state: IssueData < ' _ , CheckCommitsState > =
129+ IssueData :: load ( & mut db, & event. issue , CHECK_COMMITS_KEY ) . await ?;
130+
131+ // Handles the errors, post the new ones, hide resolved ones and don't touch the one still active
132+ if !state. data . last_errors . is_empty ( ) || !errors. is_empty ( ) {
133+ let ( errors_to_remove, errors_to_add) =
134+ calculate_error_changes ( & state. data . last_errors , & errors) ;
135+
136+ for error_to_remove in errors_to_remove {
137+ event
138+ . issue
139+ . hide_comment (
140+ & ctx. github ,
141+ & error_to_remove. 1 ,
142+ ReportedContentClassifiers :: Resolved ,
143+ )
144+ . await ?;
145+ state. data . last_errors . retain ( |e| e != & error_to_remove) ;
146+ }
147+
148+ for error_to_add in errors_to_add {
149+ let comment = event. issue . post_comment ( & ctx. github , & error_to_add) . await ?;
150+ state. data . last_errors . push ( ( error_to_add, comment. node_id ) ) ;
151+ }
152+ }
125153
126154 // We only post a new comment when we haven't posted one with the same warnings before.
127155 if !warnings. is_empty ( ) && state. data . last_warnings != warnings {
@@ -225,6 +253,28 @@ fn calculate_label_changes(
225253 ( removals, additions)
226254}
227255
256+ // Calculate the error changes
257+ fn calculate_error_changes (
258+ previous : & Vec < ( String , String ) > ,
259+ current : & Vec < String > ,
260+ ) -> ( Vec < ( String , String ) > , Vec < String > ) {
261+ let previous_set: HashSet < ( String , String ) > = previous. into_iter ( ) . cloned ( ) . collect ( ) ;
262+ let current_set: HashSet < String > = current. into_iter ( ) . cloned ( ) . collect ( ) ;
263+
264+ let removals = previous_set
265+ . iter ( )
266+ . filter ( |( e, _) | !current_set. contains ( e) )
267+ . cloned ( )
268+ . collect ( ) ;
269+ let additions = current_set
270+ . iter ( )
271+ . filter ( |e| !previous_set. iter ( ) . any ( |( e2, _) | e == & e2) )
272+ . cloned ( )
273+ . collect ( ) ;
274+
275+ ( removals, additions)
276+ }
277+
228278#[ cfg( test) ]
229279fn dummy_commit_from_body ( sha : & str , body : & str ) -> GithubCommit {
230280 use chrono:: { DateTime , FixedOffset } ;
0 commit comments