@@ -6,7 +6,7 @@ use std::sync::{Arc, RwLock};
6
6
use std:: time:: { Duration , Instant } ;
7
7
use tracing as log;
8
8
9
- static CONFIG_FILE_NAME : & str = "triagebot.toml" ;
9
+ pub ( crate ) static CONFIG_FILE_NAME : & str = "triagebot.toml" ;
10
10
const REFRESH_EVERY : Duration = Duration :: from_secs ( 2 * 60 ) ; // Every two minutes
11
11
12
12
lazy_static:: lazy_static! {
@@ -17,6 +17,7 @@ lazy_static::lazy_static! {
17
17
18
18
#[ derive( PartialEq , Eq , Debug , serde:: Deserialize ) ]
19
19
#[ serde( rename_all = "kebab-case" ) ]
20
+ #[ serde( deny_unknown_fields) ]
20
21
pub ( crate ) struct Config {
21
22
pub ( crate ) relabel : Option < RelabelConfig > ,
22
23
pub ( crate ) assign : Option < AssignConfig > ,
@@ -35,9 +36,13 @@ pub(crate) struct Config {
35
36
pub ( crate ) note : Option < NoteConfig > ,
36
37
pub ( crate ) mentions : Option < MentionsConfig > ,
37
38
pub ( crate ) no_merges : Option < NoMergesConfig > ,
39
+ // We want this validation to run even without the entry in the config file
40
+ #[ serde( default = "ValidateConfig::default" ) ]
41
+ pub ( crate ) validate_config : Option < ValidateConfig > ,
38
42
}
39
43
40
44
#[ derive( PartialEq , Eq , Debug , serde:: Deserialize ) ]
45
+ #[ serde( deny_unknown_fields) ]
41
46
pub ( crate ) struct NominateConfig {
42
47
// team name -> label
43
48
pub ( crate ) teams : HashMap < String , String > ,
@@ -68,6 +73,7 @@ impl PingConfig {
68
73
}
69
74
70
75
#[ derive( PartialEq , Eq , Debug , serde:: Deserialize ) ]
76
+ #[ serde( deny_unknown_fields) ]
71
77
pub ( crate ) struct PingTeamConfig {
72
78
pub ( crate ) message : String ,
73
79
#[ serde( default ) ]
@@ -76,6 +82,7 @@ pub(crate) struct PingTeamConfig {
76
82
}
77
83
78
84
#[ derive( PartialEq , Eq , Debug , serde:: Deserialize ) ]
85
+ #[ serde( deny_unknown_fields) ]
79
86
pub ( crate ) struct AssignConfig {
80
87
/// If `true`, then posts a warning comment if the PR is opened against a
81
88
/// different branch than the default (usually master or main).
@@ -105,6 +112,7 @@ impl AssignConfig {
105
112
}
106
113
107
114
#[ derive( PartialEq , Eq , Debug , serde:: Deserialize ) ]
115
+ #[ serde( deny_unknown_fields) ]
108
116
pub ( crate ) struct NoMergesConfig {
109
117
/// No action will be taken on PRs with these substrings in the title.
110
118
#[ serde( default ) ]
@@ -121,6 +129,7 @@ pub(crate) struct NoMergesConfig {
121
129
}
122
130
123
131
#[ derive( PartialEq , Eq , Debug , serde:: Deserialize ) ]
132
+ #[ serde( deny_unknown_fields) ]
124
133
pub ( crate ) struct NoteConfig {
125
134
#[ serde( default ) ]
126
135
_empty : ( ) ,
@@ -133,6 +142,7 @@ pub(crate) struct MentionsConfig {
133
142
}
134
143
135
144
#[ derive( PartialEq , Eq , Debug , serde:: Deserialize ) ]
145
+ #[ serde( deny_unknown_fields) ]
136
146
pub ( crate ) struct MentionsPathConfig {
137
147
pub ( crate ) message : Option < String > ,
138
148
#[ serde( default ) ]
@@ -141,22 +151,34 @@ pub(crate) struct MentionsPathConfig {
141
151
142
152
#[ derive( PartialEq , Eq , Debug , serde:: Deserialize ) ]
143
153
#[ serde( rename_all = "kebab-case" ) ]
154
+ #[ serde( deny_unknown_fields) ]
144
155
pub ( crate ) struct RelabelConfig {
145
156
#[ serde( default ) ]
146
157
pub ( crate ) allow_unauthenticated : Vec < String > ,
147
158
}
148
159
149
160
#[ derive( PartialEq , Eq , Debug , serde:: Deserialize ) ]
161
+ #[ serde( deny_unknown_fields) ]
150
162
pub ( crate ) struct ShortcutConfig {
151
163
#[ serde( default ) ]
152
164
_empty : ( ) ,
153
165
}
154
166
155
167
#[ derive( PartialEq , Eq , Debug , serde:: Deserialize ) ]
168
+ #[ serde( deny_unknown_fields) ]
156
169
pub ( crate ) struct PrioritizeConfig {
157
170
pub ( crate ) label : String ,
158
171
}
159
172
173
+ #[ derive( PartialEq , Eq , Debug , serde:: Deserialize ) ]
174
+ pub ( crate ) struct ValidateConfig { }
175
+
176
+ impl ValidateConfig {
177
+ fn default ( ) -> Option < Self > {
178
+ Some ( ValidateConfig { } )
179
+ }
180
+ }
181
+
160
182
#[ derive( PartialEq , Eq , Debug , serde:: Deserialize ) ]
161
183
pub ( crate ) struct AutolabelConfig {
162
184
#[ serde( flatten) ]
@@ -176,6 +198,7 @@ impl AutolabelConfig {
176
198
}
177
199
178
200
#[ derive( PartialEq , Eq , Debug , serde:: Deserialize ) ]
201
+ #[ serde( deny_unknown_fields) ]
179
202
pub ( crate ) struct AutolabelLabelConfig {
180
203
#[ serde( default ) ]
181
204
pub ( crate ) trigger_labels : Vec < String > ,
@@ -196,6 +219,7 @@ pub(crate) struct NotifyZulipConfig {
196
219
}
197
220
198
221
#[ derive( PartialEq , Eq , Debug , serde:: Deserialize ) ]
222
+ #[ serde( deny_unknown_fields) ]
199
223
pub ( crate ) struct NotifyZulipLabelConfig {
200
224
pub ( crate ) zulip_stream : u64 ,
201
225
pub ( crate ) topic : String ,
@@ -208,6 +232,7 @@ pub(crate) struct NotifyZulipLabelConfig {
208
232
}
209
233
210
234
#[ derive( PartialEq , Eq , Debug , serde:: Deserialize ) ]
235
+ #[ serde( deny_unknown_fields) ]
211
236
pub ( crate ) struct MajorChangeConfig {
212
237
/// A username (typically a group, e.g. T-lang) to ping on Zulip for newly
213
238
/// opened proposals.
@@ -243,18 +268,22 @@ impl MajorChangeConfig {
243
268
}
244
269
245
270
#[ derive( PartialEq , Eq , Debug , serde:: Deserialize ) ]
271
+ #[ serde( deny_unknown_fields) ]
246
272
pub ( crate ) struct GlacierConfig { }
247
273
248
274
#[ derive( PartialEq , Eq , Debug , serde:: Deserialize ) ]
275
+ #[ serde( deny_unknown_fields) ]
249
276
pub ( crate ) struct CloseConfig { }
250
277
251
278
#[ derive( PartialEq , Eq , Debug , serde:: Deserialize ) ]
279
+ #[ serde( deny_unknown_fields) ]
252
280
pub ( crate ) struct ReviewSubmittedConfig {
253
281
pub ( crate ) review_labels : Vec < String > ,
254
282
pub ( crate ) reviewed_label : String ,
255
283
}
256
284
257
285
#[ derive( PartialEq , Eq , Debug , serde:: Deserialize ) ]
286
+ #[ serde( deny_unknown_fields) ]
258
287
pub ( crate ) struct ReviewRequestedConfig {
259
288
pub ( crate ) remove_labels : Vec < String > ,
260
289
pub ( crate ) add_labels : Vec < String > ,
@@ -280,6 +309,7 @@ pub(crate) async fn get(
280
309
281
310
#[ derive( PartialEq , Eq , Debug , serde:: Deserialize ) ]
282
311
#[ serde( rename_all = "kebab-case" ) ]
312
+ #[ serde( deny_unknown_fields) ]
283
313
pub ( crate ) struct GitHubReleasesConfig {
284
314
pub ( crate ) format : ChangelogFormat ,
285
315
pub ( crate ) project_name : String ,
@@ -307,7 +337,8 @@ async fn get_fresh_config(
307
337
. await
308
338
. map_err ( |e| ConfigurationError :: Http ( Arc :: new ( e) ) ) ?
309
339
. ok_or ( ConfigurationError :: Missing ) ?;
310
- let config = Arc :: new ( toml:: from_slice :: < Config > ( & contents) . map_err ( ConfigurationError :: Toml ) ?) ;
340
+ let contents = String :: from_utf8_lossy ( & * contents) ;
341
+ let config = Arc :: new ( toml:: from_str :: < Config > ( & contents) . map_err ( ConfigurationError :: Toml ) ?) ;
311
342
log:: debug!( "fresh configuration for {}: {:?}" , repo. full_name, config) ;
312
343
Ok ( config)
313
344
}
@@ -431,6 +462,7 @@ mod tests {
431
462
review_requested: None ,
432
463
mentions: None ,
433
464
no_merges: None ,
465
+ validate_config: Some ( ValidateConfig { } ) ,
434
466
}
435
467
) ;
436
468
}
0 commit comments