@@ -24,6 +24,9 @@ pub(super) struct NoMergesInput {
2424struct NoMergesState {
2525 /// Hashes of merge commits that have already been mentioned by triagebot in a comment.
2626 mentioned_merge_commits : HashSet < String > ,
27+ /// Labels that the bot added as part of the no-merges check.
28+ #[ serde( default ) ]
29+ added_labels : Vec < String > ,
2730}
2831
2932pub ( super ) async fn parse_input (
@@ -72,10 +75,8 @@ pub(super) async fn parse_input(
7275 }
7376 }
7477
75- if merge_commits. is_empty ( ) {
76- return Ok ( None ) ;
77- }
78-
78+ // Run the handler even if we have no merge commits,
79+ // so we can take an action if some were removed.
7980 Ok ( Some ( NoMergesInput { merge_commits } ) )
8081}
8182
@@ -103,6 +104,32 @@ pub(super) async fn handle_input(
103104 let mut client = ctx. db . get ( ) . await ;
104105 let mut state: IssueData < ' _ , NoMergesState > =
105106 IssueData :: load ( & mut client, & event. issue , NO_MERGES_KEY ) . await ?;
107+
108+ // No merge commits.
109+ if input. merge_commits . is_empty ( ) {
110+ if state. data . mentioned_merge_commits . is_empty ( ) {
111+ // No merge commits from before, so do nothing.
112+ return Ok ( ( ) ) ;
113+ }
114+
115+ // Merge commits were removed, so remove the labels we added.
116+ for name in state. data . added_labels . iter ( ) {
117+ event
118+ . issue
119+ . remove_label ( & ctx. github , name)
120+ . await
121+ . context ( "failed to remove label" ) ?;
122+ }
123+
124+ // FIXME: Minimize prior no_merges comments.
125+
126+ // Clear from state.
127+ state. data . mentioned_merge_commits . clear ( ) ;
128+ state. data . added_labels . clear ( ) ;
129+ state. save ( ) . await ?;
130+ return Ok ( ( ) ) ;
131+ }
132+
106133 let first_time = state. data . mentioned_merge_commits . is_empty ( ) ;
107134
108135 let mut message = config
@@ -137,7 +164,7 @@ pub(super) async fn handle_input(
137164 if !first_time {
138165 // Check if the labels are still set.
139166 // Otherwise, they were probably removed manually.
140- let any_removed = config . labels . iter ( ) . any ( |label| {
167+ let any_removed = state . data . added_labels . iter ( ) . any ( |label| {
141168 // No label on the issue matches.
142169 event. issue . labels ( ) . iter ( ) . all ( |l| & l. name != label)
143170 } ) ;
@@ -150,13 +177,18 @@ pub(super) async fn handle_input(
150177 }
151178 }
152179
180+ let existing_labels = event. issue . labels ( ) ;
181+
182+ let mut labels = Vec :: new ( ) ;
183+ for name in config. labels . iter ( ) {
184+ // Only add labels not already on the issue.
185+ if existing_labels. iter ( ) . all ( |l| & l. name != name) {
186+ state. data . added_labels . push ( name. clone ( ) ) ;
187+ labels. push ( Label { name : name. clone ( ) } ) ;
188+ }
189+ }
190+
153191 // Set labels
154- let labels = config
155- . labels
156- . iter ( )
157- . cloned ( )
158- . map ( |name| Label { name } )
159- . collect ( ) ;
160192 event
161193 . issue
162194 . add_labels ( & ctx. github , labels)
0 commit comments