remove SoV from the public API
This was a leaky abstraction; surface everything as `Vec<T>` and handle the scalar conversion internally.
This commit is contained in:
parent
1a439ef28b
commit
d070a0bf3f
4 changed files with 38 additions and 60 deletions
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use serde::Deserialize;
|
use serde::{Deserialize, Deserializer};
|
||||||
|
|
||||||
/// `permissions` for a workflow, job, or step.
|
/// `permissions` for a workflow, job, or step.
|
||||||
#[derive(Deserialize, Debug, PartialEq)]
|
#[derive(Deserialize, Debug, PartialEq)]
|
||||||
|
@ -116,48 +116,37 @@ pub type BoE = LoE<bool>;
|
||||||
|
|
||||||
/// A "scalar or vector" type, for places in GitHub Actions where a
|
/// A "scalar or vector" type, for places in GitHub Actions where a
|
||||||
/// key can have either a scalar value or an array of values.
|
/// key can have either a scalar value or an array of values.
|
||||||
|
///
|
||||||
|
/// This only appears internally, as an intermediate type for `scalar_or_vector`.
|
||||||
#[derive(Debug, Deserialize, PartialEq)]
|
#[derive(Debug, Deserialize, PartialEq)]
|
||||||
#[serde(untagged)]
|
#[serde(untagged)]
|
||||||
pub enum SoV<T> {
|
pub(crate) enum SoV<T> {
|
||||||
One(T),
|
One(T),
|
||||||
Many(Vec<T>),
|
Many(Vec<T>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Default for SoV<T> {
|
impl<T> Into<Vec<T>> for SoV<T> {
|
||||||
fn default() -> Self {
|
fn into(self) -> Vec<T> {
|
||||||
SoV::Many(Default::default())
|
match self {
|
||||||
|
Self::One(v) => vec![v],
|
||||||
|
Self::Many(vs) => vs,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> SoV<T> {
|
pub(crate) fn scalar_or_vector<'de, D, T>(de: D) -> Result<Vec<T>, D::Error>
|
||||||
pub fn one(v: T) -> Self {
|
where
|
||||||
SoV::One(v)
|
D: Deserializer<'de>,
|
||||||
}
|
T: Deserialize<'de>,
|
||||||
|
{
|
||||||
pub fn many(vs: Vec<T>) -> Self {
|
SoV::deserialize(de).map(Into::into)
|
||||||
SoV::Many(vs)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, T> IntoIterator for &'a SoV<T> {
|
|
||||||
type Item = &'a T;
|
|
||||||
type IntoIter = std::slice::Iter<'a, T>;
|
|
||||||
|
|
||||||
fn into_iter(self) -> Self::IntoIter {
|
|
||||||
let slice = match self {
|
|
||||||
SoV::One(v) => std::slice::from_ref(v),
|
|
||||||
SoV::Many(vs) => vs.as_slice(),
|
|
||||||
};
|
|
||||||
|
|
||||||
slice.iter()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::common::{BasePermission, ExplicitPermissions};
|
use crate::common::{BasePermission, ExplicitPermissions};
|
||||||
|
|
||||||
use super::{Permissions, SoV};
|
use super::Permissions;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_permissions() {
|
fn test_permissions() {
|
||||||
|
@ -172,17 +161,4 @@ mod tests {
|
||||||
Ok(_)
|
Ok(_)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_sov_intoiterator() {
|
|
||||||
let sov_one = SoV::one("test".to_string());
|
|
||||||
assert_eq!(sov_one.into_iter().collect::<Vec<_>>(), vec!["test"]);
|
|
||||||
|
|
||||||
let sov_many = SoV::many(vec!["test-1".to_string(), "test-2".to_string()]);
|
|
||||||
assert!(matches!(sov_many, SoV::Many(_)));
|
|
||||||
assert_eq!(
|
|
||||||
sov_many.into_iter().collect::<Vec<_>>(),
|
|
||||||
vec!["test-1", "test-2"]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,8 +8,6 @@ use std::collections::{HashMap, HashSet};
|
||||||
|
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
use crate::common::SoV;
|
|
||||||
|
|
||||||
/// A `dependabot.yml` configuration file.
|
/// A `dependabot.yml` configuration file.
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(Deserialize, Debug)]
|
||||||
#[serde(rename_all = "kebab-case")]
|
#[serde(rename_all = "kebab-case")]
|
||||||
|
@ -123,7 +121,8 @@ pub struct Update {
|
||||||
// TODO: pull-request-branch-name
|
// TODO: pull-request-branch-name
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub rebase_strategy: RebaseStrategy,
|
pub rebase_strategy: RebaseStrategy,
|
||||||
pub registries: Option<SoV<String>>,
|
#[serde(default, deserialize_with = "crate::common::scalar_or_vector")]
|
||||||
|
pub registries: Vec<String>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub reviewers: HashSet<String>,
|
pub reviewers: HashSet<String>,
|
||||||
pub schedule: Schedule,
|
pub schedule: Schedule,
|
||||||
|
|
|
@ -5,7 +5,7 @@ use std::collections::HashMap;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde_yaml::Value;
|
use serde_yaml::Value;
|
||||||
|
|
||||||
use crate::common::{BoE, Env, LoE, Permissions, SoV};
|
use crate::common::{BoE, Env, LoE, Permissions};
|
||||||
|
|
||||||
use super::{Concurrency, Defaults};
|
use super::{Concurrency, Defaults};
|
||||||
|
|
||||||
|
@ -17,8 +17,8 @@ pub struct NormalJob {
|
||||||
pub name: Option<String>,
|
pub name: Option<String>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub permissions: Permissions,
|
pub permissions: Permissions,
|
||||||
#[serde(default)]
|
#[serde(default, deserialize_with = "crate::common::scalar_or_vector")]
|
||||||
pub needs: SoV<String>,
|
pub needs: Vec<String>,
|
||||||
pub r#if: Option<String>,
|
pub r#if: Option<String>,
|
||||||
pub runs_on: RunsOn,
|
pub runs_on: RunsOn,
|
||||||
pub environment: Option<DeploymentEnvironment>,
|
pub environment: Option<DeploymentEnvironment>,
|
||||||
|
@ -41,9 +41,15 @@ pub struct NormalJob {
|
||||||
#[derive(Debug, Deserialize, PartialEq)]
|
#[derive(Debug, Deserialize, PartialEq)]
|
||||||
#[serde(rename_all = "kebab-case", untagged)]
|
#[serde(rename_all = "kebab-case", untagged)]
|
||||||
pub enum RunsOn {
|
pub enum RunsOn {
|
||||||
Target(SoV<String>),
|
#[serde(deserialize_with = "crate::common::scalar_or_vector")]
|
||||||
Group { group: String },
|
Target(Vec<String>),
|
||||||
Label { label: SoV<String> },
|
Group {
|
||||||
|
group: String,
|
||||||
|
},
|
||||||
|
#[serde(deserialize_with = "crate::common::scalar_or_vector")]
|
||||||
|
Label {
|
||||||
|
label: Vec<String>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
|
@ -130,8 +136,8 @@ pub struct ReusableWorkflowCallJob {
|
||||||
pub name: Option<String>,
|
pub name: Option<String>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub permissions: Permissions,
|
pub permissions: Permissions,
|
||||||
#[serde(default)]
|
#[serde(default, deserialize_with = "crate::common::scalar_or_vector")]
|
||||||
pub needs: SoV<String>,
|
pub needs: Vec<String>,
|
||||||
pub r#if: Option<String>,
|
pub r#if: Option<String>,
|
||||||
pub uses: String,
|
pub uses: String,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
|
|
|
@ -1,12 +1,9 @@
|
||||||
use std::{env, path::Path};
|
use std::{env, path::Path};
|
||||||
|
|
||||||
use github_actions_models::{
|
use github_actions_models::workflow::{
|
||||||
common::SoV,
|
event::OptionalBody,
|
||||||
workflow::{
|
job::{RunsOn, StepBody},
|
||||||
event::OptionalBody,
|
Job, Trigger, Workflow,
|
||||||
job::{RunsOn, StepBody},
|
|
||||||
Job, Trigger, Workflow,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
fn load_workflow(name: &str) -> Workflow {
|
fn load_workflow(name: &str) -> Workflow {
|
||||||
|
@ -44,7 +41,7 @@ fn test_pip_audit_ci() {
|
||||||
assert_eq!(test_job.name, None);
|
assert_eq!(test_job.name, None);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
test_job.runs_on,
|
test_job.runs_on,
|
||||||
RunsOn::Target(SoV::one("ubuntu-latest".to_string()))
|
RunsOn::Target(vec!["ubuntu-latest".to_string()])
|
||||||
);
|
);
|
||||||
assert_eq!(test_job.steps.len(), 3);
|
assert_eq!(test_job.steps.len(), 3);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue