Skip to content

Commit 7a497a0

Browse files
authored
Merge pull request #1730 from meysam81/master
feat: validate proposed change(s) in triagebot.toml for PRs ✨
2 parents 92c3399 + 252acb2 commit 7a497a0

File tree

8 files changed

+231
-15
lines changed

8 files changed

+231
-15
lines changed

Cargo.lock

Lines changed: 71 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ hex = "0.4"
1818
parser = { path = "parser" }
1919
rust_team_data = { git = "https://github.com/rust-lang/team" }
2020
glob = "0.3.0"
21-
toml = "0.5.1"
21+
toml = "0.8.8"
2222
hyper = { version = "0.14.4", features = ["server", "stream"]}
2323
tokio = { version = "1.7.1", features = ["macros", "time", "rt"] }
2424
futures = { version = "0.3", default-features = false, features = ["std"] }

src/config.rs

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::sync::{Arc, RwLock};
66
use std::time::{Duration, Instant};
77
use tracing as log;
88

9-
static CONFIG_FILE_NAME: &str = "triagebot.toml";
9+
pub(crate) static CONFIG_FILE_NAME: &str = "triagebot.toml";
1010
const REFRESH_EVERY: Duration = Duration::from_secs(2 * 60); // Every two minutes
1111

1212
lazy_static::lazy_static! {
@@ -17,6 +17,7 @@ lazy_static::lazy_static! {
1717

1818
#[derive(PartialEq, Eq, Debug, serde::Deserialize)]
1919
#[serde(rename_all = "kebab-case")]
20+
#[serde(deny_unknown_fields)]
2021
pub(crate) struct Config {
2122
pub(crate) relabel: Option<RelabelConfig>,
2223
pub(crate) assign: Option<AssignConfig>,
@@ -35,9 +36,13 @@ pub(crate) struct Config {
3536
pub(crate) note: Option<NoteConfig>,
3637
pub(crate) mentions: Option<MentionsConfig>,
3738
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>,
3842
}
3943

4044
#[derive(PartialEq, Eq, Debug, serde::Deserialize)]
45+
#[serde(deny_unknown_fields)]
4146
pub(crate) struct NominateConfig {
4247
// team name -> label
4348
pub(crate) teams: HashMap<String, String>,
@@ -68,6 +73,7 @@ impl PingConfig {
6873
}
6974

7075
#[derive(PartialEq, Eq, Debug, serde::Deserialize)]
76+
#[serde(deny_unknown_fields)]
7177
pub(crate) struct PingTeamConfig {
7278
pub(crate) message: String,
7379
#[serde(default)]
@@ -76,6 +82,7 @@ pub(crate) struct PingTeamConfig {
7682
}
7783

7884
#[derive(PartialEq, Eq, Debug, serde::Deserialize)]
85+
#[serde(deny_unknown_fields)]
7986
pub(crate) struct AssignConfig {
8087
/// If `true`, then posts a warning comment if the PR is opened against a
8188
/// different branch than the default (usually master or main).
@@ -105,6 +112,7 @@ impl AssignConfig {
105112
}
106113

107114
#[derive(PartialEq, Eq, Debug, serde::Deserialize)]
115+
#[serde(deny_unknown_fields)]
108116
pub(crate) struct NoMergesConfig {
109117
/// No action will be taken on PRs with these substrings in the title.
110118
#[serde(default)]
@@ -121,6 +129,7 @@ pub(crate) struct NoMergesConfig {
121129
}
122130

123131
#[derive(PartialEq, Eq, Debug, serde::Deserialize)]
132+
#[serde(deny_unknown_fields)]
124133
pub(crate) struct NoteConfig {
125134
#[serde(default)]
126135
_empty: (),
@@ -133,6 +142,7 @@ pub(crate) struct MentionsConfig {
133142
}
134143

135144
#[derive(PartialEq, Eq, Debug, serde::Deserialize)]
145+
#[serde(deny_unknown_fields)]
136146
pub(crate) struct MentionsPathConfig {
137147
pub(crate) message: Option<String>,
138148
#[serde(default)]
@@ -141,22 +151,34 @@ pub(crate) struct MentionsPathConfig {
141151

142152
#[derive(PartialEq, Eq, Debug, serde::Deserialize)]
143153
#[serde(rename_all = "kebab-case")]
154+
#[serde(deny_unknown_fields)]
144155
pub(crate) struct RelabelConfig {
145156
#[serde(default)]
146157
pub(crate) allow_unauthenticated: Vec<String>,
147158
}
148159

149160
#[derive(PartialEq, Eq, Debug, serde::Deserialize)]
161+
#[serde(deny_unknown_fields)]
150162
pub(crate) struct ShortcutConfig {
151163
#[serde(default)]
152164
_empty: (),
153165
}
154166

155167
#[derive(PartialEq, Eq, Debug, serde::Deserialize)]
168+
#[serde(deny_unknown_fields)]
156169
pub(crate) struct PrioritizeConfig {
157170
pub(crate) label: String,
158171
}
159172

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+
160182
#[derive(PartialEq, Eq, Debug, serde::Deserialize)]
161183
pub(crate) struct AutolabelConfig {
162184
#[serde(flatten)]
@@ -176,6 +198,7 @@ impl AutolabelConfig {
176198
}
177199

178200
#[derive(PartialEq, Eq, Debug, serde::Deserialize)]
201+
#[serde(deny_unknown_fields)]
179202
pub(crate) struct AutolabelLabelConfig {
180203
#[serde(default)]
181204
pub(crate) trigger_labels: Vec<String>,
@@ -196,6 +219,7 @@ pub(crate) struct NotifyZulipConfig {
196219
}
197220

198221
#[derive(PartialEq, Eq, Debug, serde::Deserialize)]
222+
#[serde(deny_unknown_fields)]
199223
pub(crate) struct NotifyZulipLabelConfig {
200224
pub(crate) zulip_stream: u64,
201225
pub(crate) topic: String,
@@ -208,6 +232,7 @@ pub(crate) struct NotifyZulipLabelConfig {
208232
}
209233

210234
#[derive(PartialEq, Eq, Debug, serde::Deserialize)]
235+
#[serde(deny_unknown_fields)]
211236
pub(crate) struct MajorChangeConfig {
212237
/// A username (typically a group, e.g. T-lang) to ping on Zulip for newly
213238
/// opened proposals.
@@ -243,18 +268,22 @@ impl MajorChangeConfig {
243268
}
244269

245270
#[derive(PartialEq, Eq, Debug, serde::Deserialize)]
271+
#[serde(deny_unknown_fields)]
246272
pub(crate) struct GlacierConfig {}
247273

248274
#[derive(PartialEq, Eq, Debug, serde::Deserialize)]
275+
#[serde(deny_unknown_fields)]
249276
pub(crate) struct CloseConfig {}
250277

251278
#[derive(PartialEq, Eq, Debug, serde::Deserialize)]
279+
#[serde(deny_unknown_fields)]
252280
pub(crate) struct ReviewSubmittedConfig {
253281
pub(crate) review_labels: Vec<String>,
254282
pub(crate) reviewed_label: String,
255283
}
256284

257285
#[derive(PartialEq, Eq, Debug, serde::Deserialize)]
286+
#[serde(deny_unknown_fields)]
258287
pub(crate) struct ReviewRequestedConfig {
259288
pub(crate) remove_labels: Vec<String>,
260289
pub(crate) add_labels: Vec<String>,
@@ -280,6 +309,7 @@ pub(crate) async fn get(
280309

281310
#[derive(PartialEq, Eq, Debug, serde::Deserialize)]
282311
#[serde(rename_all = "kebab-case")]
312+
#[serde(deny_unknown_fields)]
283313
pub(crate) struct GitHubReleasesConfig {
284314
pub(crate) format: ChangelogFormat,
285315
pub(crate) project_name: String,
@@ -307,7 +337,8 @@ async fn get_fresh_config(
307337
.await
308338
.map_err(|e| ConfigurationError::Http(Arc::new(e)))?
309339
.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)?);
311342
log::debug!("fresh configuration for {}: {:?}", repo.full_name, config);
312343
Ok(config)
313344
}
@@ -431,6 +462,7 @@ mod tests {
431462
review_requested: None,
432463
mentions: None,
433464
no_merges: None,
465+
validate_config: Some(ValidateConfig {}),
434466
}
435467
);
436468
}

src/github.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -999,7 +999,7 @@ struct PullRequestEventFields {}
999999

10001000
#[derive(Clone, Debug, serde::Deserialize)]
10011001
pub struct CommitBase {
1002-
sha: String,
1002+
pub sha: String,
10031003
#[serde(rename = "ref")]
10041004
pub git_ref: String,
10051005
pub repo: Repository,

src/handlers.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ mod rfc_helper;
4646
pub mod rustc_commits;
4747
mod shortcut;
4848
pub mod types_planning_updates;
49+
mod validate_config;
4950

5051
pub async fn handle(ctx: &Context, event: &Event) -> Vec<HandlerError> {
5152
let config = config::get(&ctx.github, event.repo()).await;
@@ -166,6 +167,7 @@ issue_handlers! {
166167
no_merges,
167168
notify_zulip,
168169
review_requested,
170+
validate_config,
169171
}
170172

171173
macro_rules! command_handlers {

src/handlers/assign/tests/tests_candidates.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ use super::super::*;
44

55
/// Basic test function for testing `candidate_reviewers_from_names`.
66
fn test_from_names(
7-
teams: Option<toml::Value>,
8-
config: toml::Value,
7+
teams: Option<toml::Table>,
8+
config: toml::Table,
99
issue: serde_json::Value,
1010
names: &[&str],
1111
expected: Result<&[&str], FindReviewerError>,
@@ -32,8 +32,8 @@ fn test_from_names(
3232

3333
/// Convert the simplified input in preparation for `candidate_reviewers_from_names`.
3434
fn convert_simplified(
35-
teams: Option<toml::Value>,
36-
config: toml::Value,
35+
teams: Option<toml::Table>,
36+
config: toml::Table,
3737
issue: serde_json::Value,
3838
) -> (Teams, AssignConfig, Issue) {
3939
// Convert the simplified team config to a real team config.

src/handlers/assign/tests/tests_from_diff.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::config::AssignConfig;
55
use crate::github::parse_diff;
66
use std::fmt::Write;
77

8-
fn test_from_diff(diff: &str, config: toml::Value, expected: &[&str]) {
8+
fn test_from_diff(diff: &str, config: toml::Table, expected: &[&str]) {
99
let files = parse_diff(diff);
1010
let aconfig: AssignConfig = config.try_into().unwrap();
1111
assert_eq!(

0 commit comments

Comments
 (0)