use derive_setters::Setters;
use indexmap::IndexMap;
use merge::Merge;
use serde::{Deserialize, Serialize};
use crate::concurrency::Concurrency;
use crate::defaults::Defaults;
use crate::env::Env;
use crate::error::Result;
use crate::generate::Generate;
use crate::job::Job;
use crate::permissions::Permissions;
use crate::Event;
#[derive(Debug, Default, Serialize, Deserialize, Clone)]
#[serde(transparent)]
pub struct Jobs(pub(crate) IndexMap<String, Job>);
impl Jobs {
pub fn add(mut self, key: String, value: Job) -> Self {
self.0.insert(key, value);
self
}
pub fn get(&self, key: &str) -> Option<&Job> {
self.0.get(key)
}
}
#[derive(Debug, Default, Setters, Serialize, Deserialize, Clone)]
#[serde(rename_all = "kebab-case")]
#[setters(strip_option, into)]
pub struct Workflow {
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub env: Option<Env>,
#[serde(skip_serializing_if = "Option::is_none")]
pub run_name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub on: Option<Event>,
#[serde(skip_serializing_if = "Option::is_none")]
pub permissions: Option<Permissions>,
#[serde(skip_serializing_if = "Option::is_none")]
pub jobs: Option<Jobs>,
#[serde(skip_serializing_if = "Option::is_none")]
pub concurrency: Option<Concurrency>,
#[serde(skip_serializing_if = "Option::is_none")]
pub defaults: Option<Defaults>,
#[serde(skip_serializing_if = "Option::is_none")]
pub timeout_minutes: Option<u32>,
}
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
#[serde(rename_all = "kebab-case")]
pub struct EventAction {
#[serde(skip_serializing_if = "Vec::is_empty")]
branches: Vec<String>,
#[serde(skip_serializing_if = "Vec::is_empty")]
branches_ignore: Vec<String>,
}
impl Workflow {
pub fn new<T: ToString>(name: T) -> Self {
Self { name: Some(name.to_string()), ..Default::default() }
}
pub fn to_string(&self) -> Result<String> {
Ok(serde_yml::to_string(self)?)
}
pub fn add_job<T: ToString, J: Into<Job>>(mut self, id: T, job: J) -> Self {
let key = id.to_string();
let jobs = self.jobs.take().unwrap_or_default().add(key, job.into());
self.jobs = Some(jobs);
self
}
pub fn parse(yml: &str) -> Result<Self> {
Ok(serde_yml::from_str(yml)?)
}
pub fn generate(self) -> Result<()> {
Generate::new(self).generate()
}
pub fn add_event<T: Into<Event>>(mut self, that: T) -> Self {
if let Some(mut this) = self.on.take() {
this.merge(that.into());
self.on = Some(this);
} else {
self.on = Some(that.into());
}
self
}
pub fn add_env<T: Into<Env>>(mut self, new_env: T) -> Self {
let mut env = self.env.take().unwrap_or_default();
env.0.extend(new_env.into().0);
self.env = Some(env);
self
}
}