use super::journal::JournalEvent;
use crate::fields::text_of;
use serde_yaml::{Mapping, Value as Yaml};
use std::collections::BTreeMap;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Task {
pub name: String,
pub workflow_name: String,
pub start: String,
pub journal: Vec<JournalEvent>,
pub gates: Vec<String>,
pub artifacts: BTreeMap<String, String>,
}
impl Task {
pub fn of(payload: &Yaml) -> Task {
let journal = payload
.get("log")
.and_then(|v| v.as_sequence())
.map(|items| items.iter().map(JournalEvent::of).collect())
.unwrap_or_default();
let gates = payload
.get("gates")
.and_then(|v| v.as_sequence())
.map(|items| {
items
.iter()
.filter_map(|item| item.as_str().map(|text| text.to_string()))
.collect()
})
.unwrap_or_default();
let artifacts = payload
.get("artifacts")
.and_then(|v| v.as_mapping())
.map(|mapping| {
mapping
.iter()
.filter_map(|(key, value)| {
Some((key.as_str()?.to_string(), value.as_str()?.to_string()))
})
.collect()
})
.unwrap_or_default();
Task {
name: text_of(payload, "name"),
workflow_name: text_of(payload, "workflow"),
start: text_of(payload, "start"),
journal,
gates,
artifacts,
}
}
pub fn declared(&self, kind: &str) -> Option<String> {
let written = self.artifacts.get(kind)?.trim();
if written.is_empty() {
None
} else {
Some(written.to_string())
}
}
pub fn recorded(&self, at: &str, step: &str, detail: &str, ok: bool) -> Task {
let mut task = self.clone();
task.journal.push(JournalEvent {
at: at.to_string(),
step: step.to_string(),
detail: detail.to_string(),
ok,
});
task
}
pub fn with_gates(&self, notes: &[String]) -> Task {
let mut task = self.clone();
for note in notes {
if !task.gates.contains(note) {
task.gates.push(note.clone());
}
}
task
}
pub fn to_yaml(&self) -> Yaml {
let mut map = Mapping::new();
map.insert(Yaml::String("name".into()), Yaml::String(self.name.clone()));
map.insert(
Yaml::String("start".into()),
Yaml::String(self.start.clone()),
);
map.insert(
Yaml::String("workflow".into()),
Yaml::String(self.workflow_name.clone()),
);
map.insert(
Yaml::String("log".into()),
Yaml::Sequence(self.journal.iter().map(JournalEvent::to_yaml).collect()),
);
map.insert(
Yaml::String("gates".into()),
Yaml::Sequence(
self.gates
.iter()
.map(|note| Yaml::String(note.clone()))
.collect(),
),
);
let mut artifacts = Mapping::new();
for (key, value) in &self.artifacts {
artifacts.insert(Yaml::String(key.clone()), Yaml::String(value.clone()));
}
map.insert(Yaml::String("artifacts".into()), Yaml::Mapping(artifacts));
Yaml::Mapping(map)
}
}