use std::fmt::Debug;
use itertools::Itertools;
use miette::Diagnostic;
use serde::{Deserialize, Serialize};
use thiserror::Error;
use crate::{State, state::RunType, step, step::Step};
#[derive(Debug, Deserialize, Serialize)]
pub(crate) struct Workflow {
pub(crate) name: String,
pub(crate) help_text: Option<String>,
pub(crate) steps: Vec<Step>,
}
impl Workflow {
pub(crate) fn set_prerelease_label(&mut self, prerelease_label: &str) {
for step in &mut self.steps {
step.set_prerelease_label(prerelease_label);
}
}
}
#[derive(Debug, Error, Diagnostic)]
#[error("There are problems with the defined workflows")]
pub struct ValidationErrorCollection {
#[related]
errors: Vec<Error>,
}
#[derive(Debug, thiserror::Error, Diagnostic)]
#[error("Problem with workflow {name}")]
pub struct Error {
name: String,
#[related]
inner: Box<[step::Error; 1]>,
}
pub(crate) fn run(workflow: Workflow, mut state: RunType<State>) -> Result<(), Error> {
for step in workflow.steps {
state = match step.run(state) {
Ok(state) => state,
Err(err) => {
return Err(Error {
name: workflow.name,
inner: Box::new([err]),
});
}
};
}
Ok(())
}
#[allow(clippy::needless_pass_by_value)] pub(crate) fn validate(
workflows: Vec<Workflow>,
state: State,
) -> Result<(), ValidationErrorCollection> {
let errors = workflows
.into_iter()
.filter_map(|workflow| run(workflow, RunType::DryRun(state.clone())).err())
.collect_vec();
if errors.is_empty() {
Ok(())
} else {
Err(ValidationErrorCollection { errors })
}
}
impl std::fmt::Display for Workflow {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", &self.name)
}
}