1
1
use crate :: {
2
- config:: { NotifyZulipConfig , NotifyZulipLabelConfig } ,
2
+ config:: { NotifyZulipConfig , NotifyZulipLabelConfig , NotifyZulipTablesConfig } ,
3
3
github:: { Issue , IssuesAction , IssuesEvent , Label } ,
4
4
handlers:: Context ,
5
5
} ;
@@ -12,6 +12,9 @@ pub(super) struct NotifyZulipInput {
12
12
/// For example, if an `I-prioritize` issue is closed,
13
13
/// this field will be `I-prioritize`.
14
14
label : Label ,
15
+ /// List of strings for tables such as [notify-zulip."beta-nominated"]
16
+ /// and/or [notify-zulip."beta-nominated".compiler]
17
+ include_config_names : Vec < String > ,
15
18
}
16
19
17
20
pub ( super ) enum NotificationType {
@@ -52,26 +55,40 @@ pub(super) async fn parse_input(
52
55
fn parse_label_change_input (
53
56
event : & IssuesEvent ,
54
57
label : Label ,
55
- config : & NotifyZulipLabelConfig ,
58
+ config : & NotifyZulipTablesConfig ,
56
59
) -> Option < NotifyZulipInput > {
57
- if !has_all_required_labels ( & event. issue , config) {
58
- // Issue misses a required label, ignore this event
60
+ let mut include_config_names: Vec < String > = vec ! [ ] ;
61
+
62
+ for ( name, label_config) in & config. subtables {
63
+ if has_all_required_labels ( & event. issue , & label_config) {
64
+ match event. action {
65
+ IssuesAction :: Labeled { .. } if !label_config. messages_on_add . is_empty ( ) => {
66
+ include_config_names. push ( name. to_string ( ) ) ;
67
+ }
68
+ IssuesAction :: Unlabeled { .. } if !label_config. messages_on_remove . is_empty ( ) => {
69
+ include_config_names. push ( name. to_string ( ) ) ;
70
+ }
71
+ _ => ( ) ,
72
+ }
73
+ }
74
+ }
75
+
76
+ if include_config_names. is_empty ( ) {
77
+ // It seems that there is no match between this event and any notify-zulip config, ignore this event
59
78
return None ;
60
79
}
61
80
62
81
match event. action {
63
- IssuesAction :: Labeled { .. } if !config. messages_on_add . is_empty ( ) => {
64
- Some ( NotifyZulipInput {
65
- notification_type : NotificationType :: Labeled ,
66
- label,
67
- } )
68
- }
69
- IssuesAction :: Unlabeled { .. } if !config. messages_on_remove . is_empty ( ) => {
70
- Some ( NotifyZulipInput {
71
- notification_type : NotificationType :: Unlabeled ,
72
- label,
73
- } )
74
- }
82
+ IssuesAction :: Labeled { .. } => Some ( NotifyZulipInput {
83
+ notification_type : NotificationType :: Labeled ,
84
+ label,
85
+ include_config_names,
86
+ } ) ,
87
+ IssuesAction :: Unlabeled { .. } => Some ( NotifyZulipInput {
88
+ notification_type : NotificationType :: Unlabeled ,
89
+ label,
90
+ include_config_names,
91
+ } ) ,
75
92
_ => None ,
76
93
}
77
94
}
@@ -92,24 +109,38 @@ fn parse_close_reopen_input(
92
109
. map ( |config| ( label, config) )
93
110
} )
94
111
. flat_map ( |( label, config) | {
95
- if !has_all_required_labels ( & event. issue , config) {
96
- // Issue misses a required label, ignore this event
112
+ let mut include_config_names: Vec < String > = vec ! [ ] ;
113
+
114
+ for ( name, label_config) in & config. subtables {
115
+ if has_all_required_labels ( & event. issue , & label_config) {
116
+ match event. action {
117
+ IssuesAction :: Closed if !label_config. messages_on_close . is_empty ( ) => {
118
+ include_config_names. push ( name. to_string ( ) ) ;
119
+ }
120
+ IssuesAction :: Reopened if !label_config. messages_on_reopen . is_empty ( ) => {
121
+ include_config_names. push ( name. to_string ( ) ) ;
122
+ }
123
+ _ => ( ) ,
124
+ }
125
+ }
126
+ }
127
+
128
+ if include_config_names. is_empty ( ) {
129
+ // It seems that there is no match between this event and any notify-zulip config, ignore this event
97
130
return None ;
98
131
}
99
132
100
133
match event. action {
101
- IssuesAction :: Closed if !config. messages_on_close . is_empty ( ) => {
102
- Some ( NotifyZulipInput {
103
- notification_type : NotificationType :: Closed ,
104
- label,
105
- } )
106
- }
107
- IssuesAction :: Reopened if !config. messages_on_reopen . is_empty ( ) => {
108
- Some ( NotifyZulipInput {
109
- notification_type : NotificationType :: Reopened ,
110
- label,
111
- } )
112
- }
134
+ IssuesAction :: Closed => Some ( NotifyZulipInput {
135
+ notification_type : NotificationType :: Closed ,
136
+ label,
137
+ include_config_names,
138
+ } ) ,
139
+ IssuesAction :: Reopened => Some ( NotifyZulipInput {
140
+ notification_type : NotificationType :: Reopened ,
141
+ label,
142
+ include_config_names,
143
+ } ) ,
113
144
_ => None ,
114
145
}
115
146
} )
@@ -140,41 +171,51 @@ pub(super) async fn handle_input<'a>(
140
171
inputs : Vec < NotifyZulipInput > ,
141
172
) -> anyhow:: Result < ( ) > {
142
173
for input in inputs {
143
- let config = & config. labels [ & input. label . name ] ;
144
-
145
- let topic = & config. topic ;
146
- let topic = topic. replace ( "{number}" , & event. issue . number . to_string ( ) ) ;
147
- let mut topic = topic. replace ( "{title}" , & event. issue . title ) ;
148
- // Truncate to 60 chars (a Zulip limitation)
149
- let mut chars = topic. char_indices ( ) . skip ( 59 ) ;
150
- if let ( Some ( ( len, _) ) , Some ( _) ) = ( chars. next ( ) , chars. next ( ) ) {
151
- topic. truncate ( len) ;
152
- topic. push ( '…' ) ;
174
+ let tables_config = & config. labels [ & input. label . name ] ;
175
+
176
+ // Get valid label configs
177
+ let mut label_configs: Vec < & NotifyZulipLabelConfig > = vec ! [ ] ;
178
+ for name in input. include_config_names {
179
+ label_configs. push ( & tables_config. subtables [ & name] ) ;
153
180
}
154
181
155
- let msgs = match input. notification_type {
156
- NotificationType :: Labeled => & config. messages_on_add ,
157
- NotificationType :: Unlabeled => & config. messages_on_remove ,
158
- NotificationType :: Closed => & config. messages_on_close ,
159
- NotificationType :: Reopened => & config. messages_on_reopen ,
160
- } ;
182
+ for label_config in label_configs {
183
+ let config = label_config;
161
184
162
- let recipient = crate :: zulip:: Recipient :: Stream {
163
- id : config. zulip_stream ,
164
- topic : & topic,
165
- } ;
185
+ let topic = & config. topic ;
186
+ let topic = topic. replace ( "{number}" , & event. issue . number . to_string ( ) ) ;
187
+ let mut topic = topic. replace ( "{title}" , & event. issue . title ) ;
188
+ // Truncate to 60 chars (a Zulip limitation)
189
+ let mut chars = topic. char_indices ( ) . skip ( 59 ) ;
190
+ if let ( Some ( ( len, _) ) , Some ( _) ) = ( chars. next ( ) , chars. next ( ) ) {
191
+ topic. truncate ( len) ;
192
+ topic. push ( '…' ) ;
193
+ }
194
+
195
+ let msgs = match input. notification_type {
196
+ NotificationType :: Labeled => & config. messages_on_add ,
197
+ NotificationType :: Unlabeled => & config. messages_on_remove ,
198
+ NotificationType :: Closed => & config. messages_on_close ,
199
+ NotificationType :: Reopened => & config. messages_on_reopen ,
200
+ } ;
166
201
167
- for msg in msgs {
168
- let msg = msg . replace ( "{number}" , & event . issue . number . to_string ( ) ) ;
169
- let msg = msg . replace ( "{title}" , & event . issue . title ) ;
170
- let msg = replace_team_to_be_nominated ( & event . issue . labels , msg ) ;
202
+ let recipient = crate :: zulip :: Recipient :: Stream {
203
+ id : config . zulip_stream ,
204
+ topic : & topic ,
205
+ } ;
171
206
172
- crate :: zulip:: MessageApiRequest {
173
- recipient,
174
- content : & msg,
207
+ for msg in msgs {
208
+ let msg = msg. replace ( "{number}" , & event. issue . number . to_string ( ) ) ;
209
+ let msg = msg. replace ( "{title}" , & event. issue . title ) ;
210
+ let msg = replace_team_to_be_nominated ( & event. issue . labels , msg) ;
211
+
212
+ crate :: zulip:: MessageApiRequest {
213
+ recipient,
214
+ content : & msg,
215
+ }
216
+ . send ( & ctx. github . raw ( ) )
217
+ . await ?;
175
218
}
176
- . send ( & ctx. github . raw ( ) )
177
- . await ?;
178
219
}
179
220
}
180
221
0 commit comments