@@ -14,6 +14,8 @@ pub(super) enum Invocation {
1414 NewProposal ,
1515 AcceptedProposal ,
1616 Rename { prev_issue : ZulipGitHubReference } ,
17+ ConcernsAdded ,
18+ ConcernsResolved ,
1719}
1820
1921pub ( super ) async fn parse_input (
@@ -61,6 +63,21 @@ pub(super) async fn parse_input(
6163 return Ok ( Some ( Invocation :: AcceptedProposal ) ) ;
6264 }
6365
66+ // If the concerns label was added, then considered that the
67+ // major change is blocked
68+ if matches ! ( & event. action, IssuesAction :: Labeled { label } if Some ( & label. name) == config. concerns_label. as_ref( ) )
69+ {
70+ return Ok ( Some ( Invocation :: ConcernsAdded ) ) ;
71+ }
72+
73+ // If the concerns label was removed, then considered that
74+ // all concerns have been resolved; the major change is no
75+ // longer blocked.
76+ if matches ! ( & event. action, IssuesAction :: Unlabeled { label: Some ( label) } if Some ( & label. name) == config. concerns_label. as_ref( ) )
77+ {
78+ return Ok ( Some ( Invocation :: ConcernsResolved ) ) ;
79+ }
80+
6481 // Opening an issue with a label assigned triggers both
6582 // "Opened" and "Labeled" events.
6683 //
@@ -99,18 +116,24 @@ pub(super) async fn handle_input(
99116 cmnt. post ( & ctx. github ) . await ?;
100117 return Ok ( ( ) ) ;
101118 }
102- let zulip_msg = match cmd {
103- Invocation :: NewProposal => format ! (
104- "A new proposal has been announced: [{} #{}]({}). It will be \
105- announced at the next meeting to try and draw attention to it, \
106- but usually MCPs are not discussed during triage meetings. If \
107- you think this would benefit from discussion amongst the \
108- team, consider proposing a design meeting.",
109- event. issue. title, event. issue. number, event. issue. html_url,
119+ let ( zulip_msg, label_to_add) = match cmd {
120+ Invocation :: NewProposal => (
121+ format ! (
122+ "A new proposal has been announced: [{} #{}]({}). It will be \
123+ announced at the next meeting to try and draw attention to it, \
124+ but usually MCPs are not discussed during triage meetings. If \
125+ you think this would benefit from discussion amongst the \
126+ team, consider proposing a design meeting.",
127+ event. issue. title, event. issue. number, event. issue. html_url,
128+ ) ,
129+ Some ( & config. meeting_label ) ,
110130 ) ,
111- Invocation :: AcceptedProposal => format ! (
112- "This proposal has been accepted: [#{}]({})." ,
113- event. issue. number, event. issue. html_url,
131+ Invocation :: AcceptedProposal => (
132+ format ! (
133+ "This proposal has been accepted: [#{}]({})." ,
134+ event. issue. number, event. issue. html_url,
135+ ) ,
136+ Some ( & config. meeting_label ) ,
114137 ) ,
115138 Invocation :: Rename { prev_issue } => {
116139 let issue = & event. issue ;
@@ -167,13 +190,32 @@ pub(super) async fn handle_input(
167190
168191 return Ok ( ( ) ) ;
169192 }
193+ Invocation :: ConcernsAdded => (
194+ // Ideally, we would remove the `enabled_label` (if present) and add it back once all concerns are resolved.
195+ //
196+ // However, since this handler is stateless, we can't track when to re-add it, it's also a bit unclear if it
197+ // should be re-added at all. Also historically the `enable_label` wasn't removed either, so we don't touch it.
198+ format ! ( "Concern(s) have been raised on the [associated GitHub issue]({}). This proposal is now blocked until those concerns are fully resolved." , event. issue. html_url) ,
199+ None
200+ ) ,
201+ Invocation :: ConcernsResolved => (
202+ if event. issue . labels ( ) . contains ( & Label {
203+ name : config. enabling_label . to_string ( ) ,
204+ } ) {
205+ format ! ( "All concerns on the [associated GitHub issue]({}) have been resolved, this proposal is no longer blocked, and will be approved in 10 days if no (new) objections are raised." , event. issue. html_url)
206+ } else {
207+ format ! ( "All concerns on the [associated GitHub issue]({}) have been resolved, this proposal is no longer blocked." , event. issue. html_url)
208+ } ,
209+ None
210+ )
170211 } ;
212+
171213 handle (
172214 ctx,
173215 config,
174216 & event. issue ,
175217 zulip_msg,
176- config . meeting_label . clone ( ) ,
218+ label_to_add . cloned ( ) ,
177219 cmd == Invocation :: NewProposal ,
178220 )
179221 . await
@@ -228,7 +270,7 @@ pub(super) async fn handle_command(
228270 config,
229271 issue,
230272 zulip_msg,
231- config. second_label . clone ( ) ,
273+ Some ( config. second_label . clone ( ) ) ,
232274 false ,
233275 )
234276 . await
@@ -239,10 +281,11 @@ async fn handle(
239281 config : & MajorChangeConfig ,
240282 issue : & Issue ,
241283 zulip_msg : String ,
242- label_to_add : String ,
284+ label_to_add : Option < String > ,
243285 new_proposal : bool ,
244286) -> anyhow:: Result < ( ) > {
245- let github_req = issue. add_labels ( & ctx. github , vec ! [ Label { name: label_to_add } ] ) ;
287+ let github_req = label_to_add
288+ . map ( |label_to_add| issue. add_labels ( & ctx. github , vec ! [ Label { name: label_to_add } ] ) ) ;
246289
247290 let partial_issue = issue. to_zulip_github_reference ( ) ;
248291 let zulip_topic = zulip_topic_from_issue ( & partial_issue) ;
@@ -292,9 +335,13 @@ See documentation at [https://forge.rust-lang.org](https://forge.rust-lang.org/c
292335
293336 let zulip_req = zulip_req. send ( & ctx. zulip ) ;
294337
295- let ( gh_res, zulip_res) = futures:: join!( github_req, zulip_req) ;
296- zulip_res. context ( "zulip post failed" ) ?;
297- gh_res. context ( "label setting failed" ) ?;
338+ if let Some ( github_req) = github_req {
339+ let ( gh_res, zulip_res) = futures:: join!( github_req, zulip_req) ;
340+ zulip_res. context ( "zulip post failed" ) ?;
341+ gh_res. context ( "label setting failed" ) ?;
342+ } else {
343+ zulip_req. await . context ( "zulip post failed" ) ?;
344+ }
298345 Ok ( ( ) )
299346}
300347
0 commit comments