From 068be06e0e28926de3a204ae83639f8a07302d41 Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Fri, 12 Jan 2024 21:18:35 -0500 Subject: [PATCH] hackety hack --- src/dependabot/v2.rs | 93 +++++++++++++++---- tests/sample-dependabot/v2/pip-audit.yml | 13 +++ .../sample-dependabot/v2/sigstore-python.yml | 30 ++++++ tests/test_dependabot_v2.rs | 64 +++++++++++++ 4 files changed, 183 insertions(+), 17 deletions(-) create mode 100644 tests/sample-dependabot/v2/pip-audit.yml create mode 100644 tests/sample-dependabot/v2/sigstore-python.yml create mode 100644 tests/test_dependabot_v2.rs diff --git a/src/dependabot/v2.rs b/src/dependabot/v2.rs index 821505a..9a3b3a3 100644 --- a/src/dependabot/v2.rs +++ b/src/dependabot/v2.rs @@ -1,16 +1,17 @@ //! "v2" Dependabot models. +//! +//! Resources: +//! * [Configuration options for the `dependabot.yml` file](https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file) +//! * [JSON Schema for Dependabot v2](https://json.schemastore.org/dependabot-2.0.json) -use std::{ - collections::{HashMap, HashSet}, - default, -}; +use std::collections::{HashMap, HashSet}; use serde::Deserialize; use crate::common::SoV; /// A `dependabot.yml` configuration file. -#[derive(Deserialize)] +#[derive(Deserialize, Debug)] #[serde(rename_all = "kebab-case")] pub struct Dependabot { /// Invariant: `2` @@ -23,7 +24,7 @@ pub struct Dependabot { } /// Different registries known to Dependabot. -#[derive(Deserialize)] +#[derive(Deserialize, Debug)] #[serde(rename_all = "kebab-case", tag = "type")] pub enum Registry { ComposerRepository { @@ -91,7 +92,7 @@ pub enum Registry { } /// A single `update` directive. -#[derive(Deserialize)] +#[derive(Deserialize, Debug)] #[serde(rename_all = "kebab-case")] pub struct Update { #[serde(default)] @@ -125,6 +126,11 @@ pub struct Update { pub registries: Option>, #[serde(default)] pub reviewers: HashSet, + pub schedule: Schedule, + pub target_branch: Option, + #[serde(default)] + pub vendor: bool, + pub versioning_strategy: Option, } #[inline] @@ -138,14 +144,16 @@ fn default_open_pull_requests_limit() -> u64 { 5 } -#[derive(Deserialize)] +/// Allow rules for Dependabot updates. +#[derive(Deserialize, Debug)] #[serde(rename_all = "kebab-case")] pub struct Allow { pub dependency_name: Option, pub dependency_type: Option, } -#[derive(Deserialize)] +/// Dependency types in `allow` rules. +#[derive(Deserialize, Debug)] #[serde(rename_all = "kebab-case")] pub enum DependencyType { Direct, @@ -155,7 +163,8 @@ pub enum DependencyType { Development, } -#[derive(Deserialize)] +/// Commit message settings for Dependabot updates. +#[derive(Deserialize, Debug)] #[serde(rename_all = "kebab-case")] pub struct CommitMessage { pub prefix: Option, @@ -164,7 +173,8 @@ pub struct CommitMessage { pub include: Option, } -#[derive(Deserialize)] +/// Group settings for batched updates. +#[derive(Deserialize, Debug)] #[serde(rename_all = "kebab-case")] pub struct Group { /// This can only be [`DependencyType::Development`] or @@ -174,10 +184,12 @@ pub struct Group { pub patterns: HashSet, #[serde(default)] pub exclude_patterns: HashSet, + #[serde(default)] pub update_types: HashSet, } -#[derive(Deserialize, Hash, Eq, PartialEq)] +/// Update types for grouping. +#[derive(Deserialize, Debug, Hash, Eq, PartialEq)] #[serde(rename_all = "kebab-case")] pub enum UpdateType { Major, @@ -185,7 +197,8 @@ pub enum UpdateType { Patch, } -#[derive(Deserialize)] +/// Dependency ignore settings for updates. +#[derive(Deserialize, Debug)] #[serde(rename_all = "kebab-case")] pub struct Ignore { pub dependency_name: Option, @@ -197,7 +210,8 @@ pub struct Ignore { pub versions: HashSet, } -#[derive(Deserialize, Default)] +/// An "allow"/"deny" toggle. +#[derive(Deserialize, Debug, Default)] #[serde(rename_all = "kebab-case")] pub enum AllowDeny { Allow, @@ -205,7 +219,8 @@ pub enum AllowDeny { Deny, } -#[derive(Deserialize)] +/// Supported packaging ecosystems. +#[derive(Deserialize, Debug, PartialEq)] #[serde(rename_all = "kebab-case")] pub enum PackageEcosystem { Bundler, @@ -214,7 +229,7 @@ pub enum PackageEcosystem { Docker, Elm, Gitsubmodule, - GitHubActions, + GithubActions, Gomod, Gradle, Maven, @@ -227,10 +242,54 @@ pub enum PackageEcosystem { Terraform, } -#[derive(Deserialize, Default)] +/// Rebase strategies for Dependabot updates. +#[derive(Deserialize, Debug, Default, PartialEq)] #[serde(rename_all = "kebab-case")] pub enum RebaseStrategy { #[default] Auto, Disabled, } + +/// Scheduling settings for Dependabot updates. +#[derive(Deserialize, Debug)] +#[serde(rename_all = "kebab-case")] +pub struct Schedule { + pub interval: Interval, + pub day: Option, + pub time: Option, + pub timezone: Option, +} + +/// Schedule intervals. +#[derive(Deserialize, Debug, PartialEq)] +#[serde(rename_all = "kebab-case")] +pub enum Interval { + Daily, + Weekly, + Monthly, +} + +/// Days of the week. +#[derive(Deserialize, Debug, PartialEq)] +#[serde(rename_all = "kebab-case")] +pub enum Day { + Monday, + Tuesday, + Wednesday, + Thursday, + Friday, + Saturday, + Sunday, +} + +/// Versioning strategies. +#[derive(Deserialize, Debug, PartialEq)] +#[serde(rename_all = "kebab-case")] +pub enum VersioningStrategy { + Auto, + Increase, + IncreaseIfNecessary, + LockfileOnly, + Widen, +} diff --git a/tests/sample-dependabot/v2/pip-audit.yml b/tests/sample-dependabot/v2/pip-audit.yml new file mode 100644 index 0000000..cd48b33 --- /dev/null +++ b/tests/sample-dependabot/v2/pip-audit.yml @@ -0,0 +1,13 @@ +# https://github.com/pypa/pip-audit/blob/cea0e0276f1208cfcbda0c5d69b4fc0c084747b2/.github/dependabot.yml +version: 2 + +updates: + - package-ecosystem: pip + directory: / + schedule: + interval: daily + + - package-ecosystem: github-actions + directory: / + schedule: + interval: daily diff --git a/tests/sample-dependabot/v2/sigstore-python.yml b/tests/sample-dependabot/v2/sigstore-python.yml new file mode 100644 index 0000000..9083000 --- /dev/null +++ b/tests/sample-dependabot/v2/sigstore-python.yml @@ -0,0 +1,30 @@ +# https://github.com/sigstore/sigstore-python/blob/e0168a781b87d059fde05dfdfe0ce82e564ce095/.github/dependabot.yml +version: 2 + +updates: + - package-ecosystem: pip + directory: / + schedule: + interval: daily + + - package-ecosystem: github-actions + directory: / + schedule: + interval: daily + open-pull-requests-limit: 99 + rebase-strategy: "disabled" + groups: + actions: + patterns: + - "*" + + - package-ecosystem: github-actions + directory: .github/actions/upload-coverage/ + schedule: + interval: daily + open-pull-requests-limit: 99 + rebase-strategy: "disabled" + groups: + actions: + patterns: + - "*" diff --git a/tests/test_dependabot_v2.rs b/tests/test_dependabot_v2.rs new file mode 100644 index 0000000..5f14e58 --- /dev/null +++ b/tests/test_dependabot_v2.rs @@ -0,0 +1,64 @@ +use std::{collections::HashSet, path::Path}; + +use glomar_models::dependabot::v2::{Dependabot, Interval, PackageEcosystem, RebaseStrategy}; + +fn load_dependabot(name: &str) -> Dependabot { + let workflow_path = Path::new(env!("CARGO_MANIFEST_DIR")) + .join("tests/sample-dependabot/v2") + .join(name); + let dependabot_contents = std::fs::read_to_string(workflow_path).unwrap(); + serde_yaml::from_str(&dependabot_contents).unwrap() +} + +#[test] +fn test_load_all() { + let sample_configs = Path::new(env!("CARGO_MANIFEST_DIR")).join("tests/sample-dependabot/v2"); + + for sample_config in std::fs::read_dir(&sample_configs).unwrap() { + let sample_workflow = sample_config.unwrap().path(); + let contents = std::fs::read_to_string(sample_workflow).unwrap(); + serde_yaml::from_str::(&contents).unwrap(); + } +} + +#[test] +fn test_contents() { + let dependabot = load_dependabot("sigstore-python.yml"); + + assert_eq!(dependabot.version, 2); + assert_eq!(dependabot.updates.len(), 3); + + let pip = &dependabot.updates[0]; + assert_eq!(pip.package_ecosystem, PackageEcosystem::Pip); + assert_eq!(pip.directory, "/"); + assert_eq!(pip.schedule.interval, Interval::Daily); + assert_eq!(pip.open_pull_requests_limit, 5); // default + + let github_actions = &dependabot.updates[1]; + assert_eq!( + github_actions.package_ecosystem, + PackageEcosystem::GithubActions + ); + assert_eq!(github_actions.directory, "/"); + assert_eq!(github_actions.open_pull_requests_limit, 99); + assert_eq!(github_actions.rebase_strategy, RebaseStrategy::Disabled); + assert_eq!(github_actions.groups.len(), 1); + assert_eq!( + github_actions.groups["actions"].patterns, + HashSet::from(["*".to_string()]) + ); + + let github_actions = &dependabot.updates[2]; + assert_eq!( + github_actions.package_ecosystem, + PackageEcosystem::GithubActions + ); + assert_eq!(github_actions.directory, ".github/actions/upload-coverage/"); + assert_eq!(github_actions.open_pull_requests_limit, 99); + assert_eq!(github_actions.rebase_strategy, RebaseStrategy::Disabled); + assert_eq!(github_actions.groups.len(), 1); + assert_eq!( + github_actions.groups["actions"].patterns, + HashSet::from(["*".to_string()]) + ); +}