Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: validate proposed change(s) in triagebot.toml for PRs ✨ #1730

Merged
merged 3 commits into from
Jan 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 71 additions & 6 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ hex = "0.4"
parser = { path = "parser" }
rust_team_data = { git = "https://github.com/rust-lang/team" }
glob = "0.3.0"
toml = "0.5.1"
toml = "0.8.8"
hyper = { version = "0.14.4", features = ["server", "stream"]}
tokio = { version = "1.7.1", features = ["macros", "time", "rt"] }
futures = { version = "0.3", default-features = false, features = ["std"] }
Expand Down
36 changes: 34 additions & 2 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::sync::{Arc, RwLock};
use std::time::{Duration, Instant};
use tracing as log;

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

lazy_static::lazy_static! {
Expand All @@ -17,6 +17,7 @@ lazy_static::lazy_static! {

#[derive(PartialEq, Eq, Debug, serde::Deserialize)]
#[serde(rename_all = "kebab-case")]
#[serde(deny_unknown_fields)]
pub(crate) struct Config {
pub(crate) relabel: Option<RelabelConfig>,
pub(crate) assign: Option<AssignConfig>,
Expand All @@ -35,9 +36,13 @@ pub(crate) struct Config {
pub(crate) note: Option<NoteConfig>,
pub(crate) mentions: Option<MentionsConfig>,
pub(crate) no_merges: Option<NoMergesConfig>,
// We want this validation to run even without the entry in the config file
#[serde(default = "ValidateConfig::default")]
pub(crate) validate_config: Option<ValidateConfig>,
}

#[derive(PartialEq, Eq, Debug, serde::Deserialize)]
#[serde(deny_unknown_fields)]
pub(crate) struct NominateConfig {
// team name -> label
pub(crate) teams: HashMap<String, String>,
Expand Down Expand Up @@ -68,6 +73,7 @@ impl PingConfig {
}

#[derive(PartialEq, Eq, Debug, serde::Deserialize)]
#[serde(deny_unknown_fields)]
pub(crate) struct PingTeamConfig {
pub(crate) message: String,
#[serde(default)]
Expand All @@ -76,6 +82,7 @@ pub(crate) struct PingTeamConfig {
}

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

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

#[derive(PartialEq, Eq, Debug, serde::Deserialize)]
#[serde(deny_unknown_fields)]
pub(crate) struct NoteConfig {
#[serde(default)]
_empty: (),
Expand All @@ -133,6 +142,7 @@ pub(crate) struct MentionsConfig {
}

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

#[derive(PartialEq, Eq, Debug, serde::Deserialize)]
#[serde(rename_all = "kebab-case")]
#[serde(deny_unknown_fields)]
pub(crate) struct RelabelConfig {
#[serde(default)]
pub(crate) allow_unauthenticated: Vec<String>,
}

#[derive(PartialEq, Eq, Debug, serde::Deserialize)]
#[serde(deny_unknown_fields)]
pub(crate) struct ShortcutConfig {
#[serde(default)]
_empty: (),
}

#[derive(PartialEq, Eq, Debug, serde::Deserialize)]
#[serde(deny_unknown_fields)]
pub(crate) struct PrioritizeConfig {
pub(crate) label: String,
}

#[derive(PartialEq, Eq, Debug, serde::Deserialize)]
pub(crate) struct ValidateConfig {}

impl ValidateConfig {
fn default() -> Option<Self> {
Some(ValidateConfig {})
}
}

#[derive(PartialEq, Eq, Debug, serde::Deserialize)]
pub(crate) struct AutolabelConfig {
#[serde(flatten)]
Expand All @@ -176,6 +198,7 @@ impl AutolabelConfig {
}

#[derive(PartialEq, Eq, Debug, serde::Deserialize)]
#[serde(deny_unknown_fields)]
pub(crate) struct AutolabelLabelConfig {
#[serde(default)]
pub(crate) trigger_labels: Vec<String>,
Expand All @@ -196,6 +219,7 @@ pub(crate) struct NotifyZulipConfig {
}

#[derive(PartialEq, Eq, Debug, serde::Deserialize)]
#[serde(deny_unknown_fields)]
pub(crate) struct NotifyZulipLabelConfig {
pub(crate) zulip_stream: u64,
pub(crate) topic: String,
Expand All @@ -208,6 +232,7 @@ pub(crate) struct NotifyZulipLabelConfig {
}

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

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

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

#[derive(PartialEq, Eq, Debug, serde::Deserialize)]
#[serde(deny_unknown_fields)]
pub(crate) struct ReviewSubmittedConfig {
pub(crate) review_labels: Vec<String>,
pub(crate) reviewed_label: String,
}

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

#[derive(PartialEq, Eq, Debug, serde::Deserialize)]
#[serde(rename_all = "kebab-case")]
#[serde(deny_unknown_fields)]
pub(crate) struct GitHubReleasesConfig {
pub(crate) format: ChangelogFormat,
pub(crate) project_name: String,
Expand Down Expand Up @@ -307,7 +337,8 @@ async fn get_fresh_config(
.await
.map_err(|e| ConfigurationError::Http(Arc::new(e)))?
.ok_or(ConfigurationError::Missing)?;
let config = Arc::new(toml::from_slice::<Config>(&contents).map_err(ConfigurationError::Toml)?);
let contents = String::from_utf8_lossy(&*contents);
let config = Arc::new(toml::from_str::<Config>(&contents).map_err(ConfigurationError::Toml)?);
log::debug!("fresh configuration for {}: {:?}", repo.full_name, config);
Ok(config)
}
Expand Down Expand Up @@ -431,6 +462,7 @@ mod tests {
review_requested: None,
mentions: None,
no_merges: None,
validate_config: Some(ValidateConfig {}),
}
);
}
Expand Down
2 changes: 1 addition & 1 deletion src/github.rs
Original file line number Diff line number Diff line change
Expand Up @@ -999,7 +999,7 @@ struct PullRequestEventFields {}

#[derive(Clone, Debug, serde::Deserialize)]
pub struct CommitBase {
sha: String,
pub sha: String,
#[serde(rename = "ref")]
pub git_ref: String,
pub repo: Repository,
Expand Down
2 changes: 2 additions & 0 deletions src/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ mod rfc_helper;
pub mod rustc_commits;
mod shortcut;
pub mod types_planning_updates;
mod validate_config;

pub async fn handle(ctx: &Context, event: &Event) -> Vec<HandlerError> {
let config = config::get(&ctx.github, event.repo()).await;
Expand Down Expand Up @@ -166,6 +167,7 @@ issue_handlers! {
no_merges,
notify_zulip,
review_requested,
validate_config,
}

macro_rules! command_handlers {
Expand Down
8 changes: 4 additions & 4 deletions src/handlers/assign/tests/tests_candidates.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ use super::super::*;

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

/// Convert the simplified input in preparation for `candidate_reviewers_from_names`.
fn convert_simplified(
teams: Option<toml::Value>,
config: toml::Value,
teams: Option<toml::Table>,
config: toml::Table,
issue: serde_json::Value,
) -> (Teams, AssignConfig, Issue) {
// Convert the simplified team config to a real team config.
Expand Down
2 changes: 1 addition & 1 deletion src/handlers/assign/tests/tests_from_diff.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::config::AssignConfig;
use crate::github::parse_diff;
use std::fmt::Write;

fn test_from_diff(diff: &str, config: toml::Value, expected: &[&str]) {
fn test_from_diff(diff: &str, config: toml::Table, expected: &[&str]) {
let files = parse_diff(diff);
let aconfig: AssignConfig = config.try_into().unwrap();
assert_eq!(
Expand Down
Loading
Loading