Skip to content

Commit

Permalink
Merge pull request #8 from abrunner94/feat/task-order
Browse files Browse the repository at this point in the history
Feat/task order
  • Loading branch information
abrunner94 authored Oct 21, 2022
2 parents b30e3e7 + d538f35 commit 25c9692
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 51 deletions.
64 changes: 37 additions & 27 deletions cli/src/commands.rs
Original file line number Diff line number Diff line change
@@ -1,35 +1,42 @@
use std::env;
use std::path::PathBuf;

use clap::ArgMatches;

use core::task::TaskBuilder;
use core::workflow::{Workflow, WorkflowBuilder};

pub fn create_workflow_file(args: &ArgMatches) {
let cwd = env::current_dir()
.unwrap_or_else(|_| PathBuf::from("could not get cwd"))
.to_str()
.unwrap()
.to_string();
let cwd = match env::current_dir() {
Ok(cwd) => cwd.to_str().unwrap().to_string(),
Err(e) => {
let msg = "Could not get current working directory".to_string();
log::error!("{}: {}", &msg, &e);
return;
}
};

// TODO: Check if a Workfile.yaml exists in cwd
// If so, create a Workfile2.yaml file, and so on
let name = args.get_one::<String>("name").unwrap().to_string();
let path = format!("{}/{}.yaml", &cwd, &name);
let name = match args.get_one::<String>("name") {
None => {
log::warn!("No argument for name has been found");
return;
}
Some(name) => name.to_string(),
};

let path = format!("{}/{}.yaml", &cwd, &name);
let workflow = WorkflowBuilder::new(name)
.add_task(
TaskBuilder::new("example_task".to_string())
.commands(vec!["echo hello".to_string(), "echo world".to_string()])
.build(),
)
.add_defaults(vec!["example_task".to_string()])
.build();

match workflow.to_file(path.as_str()) {
Ok(workflow) => {
workflow.start(None);
log::info!("Created workflow file");
workflow.start(None);
}
Err(err) => {
let msg = "Could not create workflow".to_string();
Expand All @@ -39,20 +46,23 @@ pub fn create_workflow_file(args: &ArgMatches) {
}

pub fn run_workflow_files(args: &ArgMatches) {
args.get_many::<String>("files")
.unwrap_or_default()
.map(|v| v.as_str())
.collect::<Vec<_>>()
.into_iter()
.for_each(|f| {
log::info!("Running workfile {}", f);
let workflow = Workflow::from_file(f);
match workflow {
Ok(workflow) => workflow.start(None),
Err(err) => {
let msg = "Could not start workflow".to_string();
log::error!("{}: {}", &msg, &err);
}
}
});
match args.get_many::<String>("files") {
None => log::warn!("No arguments have been passed in for files"),
Some(args) => {
args.map(|v| v.as_str())
.collect::<Vec<_>>()
.into_iter()
.for_each(|f| {
log::info!("Running workfile {}", f);
let workflow = Workflow::from_file(f);
match workflow {
Ok(workflow) => workflow.start(None),
Err(err) => {
let msg = "Could not start workflow".to_string();
log::error!("{}: {}", &msg, &err);
}
}
});
}
}
}
9 changes: 6 additions & 3 deletions core/src/task.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,12 @@ impl Task {
pub fn start(&mut self) {
for command in self.cmds.iter() {
let cmd = &command;
// TODO: Add Windows powershell support
if run_cmd!(bash -c $cmd).is_err() {
log::error!("could not run task");
let run = match cfg!(target_os = "windows") {
true => run_cmd!(cmd /C $cmd),
false => run_cmd!(bash -c $cmd),
};
if run.is_err() {
log::error!("Could not run task");
}
}
}
Expand Down
112 changes: 91 additions & 21 deletions core/src/workflow.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
use std::fs::{File, OpenOptions};
use std::io::Error;
use std::io::{Error, ErrorKind};

use serde::{Deserialize, Serialize};
use serde_yaml::Value;

use crate::task::{Task, TaskBuilder};

#[derive(Default, Serialize, Debug, Eq, PartialEq)]
pub struct Workflow {
name: String,
default: Vec<String>,
tasks: Vec<Task>,
}

Expand Down Expand Up @@ -40,9 +42,17 @@ impl Workflow {
pub fn to_file(self, file_name: &str) -> Result<Workflow, Error> {
let workflow = Workflow {
name: self.name,
default: self.default,
tasks: self.tasks,
};
let yaml = serde_yaml::to_value(&workflow).expect("could not convert struct to string");

let yaml = match serde_yaml::to_value(&workflow) {
Ok(yaml) => yaml,
Err(_) => {
let msg = format!("Could not convert yaml file: {}", &file_name);
return Err(Error::new(ErrorKind::InvalidInput, msg));
}
};

if workflow.tasks.is_empty() {
log::info!("No tasks have been found. Skipping file creation.");
Expand All @@ -57,7 +67,13 @@ impl Workflow {
}
};

serde_yaml::to_writer(file, &yaml).expect("could not write yaml file");
match serde_yaml::to_writer(file, &yaml) {
Ok(written) => written,
Err(_) => {
let msg = format!("{} could not write yaml to file", &file_name);
return Err(Error::new(ErrorKind::Other, msg));
}
}

Ok(workflow)
}
Expand All @@ -71,28 +87,71 @@ impl Workflow {
}
};

let yaml: serde_yaml::Value =
serde_yaml::from_reader(file).expect("could not read yaml file");
let yaml: Value = match serde_yaml::from_reader(file) {
Ok(read) => read,
Err(_) => {
return Err(Error::new(ErrorKind::Other, "Could not read yaml file"));
}
};

let default = &yaml["default"];
let tasks = &yaml["tasks"];
let workflow_name = &yaml["name"];
let mut workflow_tasks: Vec<Task> = Vec::new();

for task in tasks.as_sequence().unwrap().iter() {
let commands = task["cmds"].as_sequence().unwrap();

let commands_as_str: Vec<String> = commands
.iter()
.map(|c| {
let value = c.as_str();
String::from(value.unwrap())
})
.collect();

workflow_tasks.push(
TaskBuilder::new(String::from(task["name"].as_str().unwrap()))
.commands(commands_as_str)
.build(),
)
// Build up default task list
let default_tasks: Vec<Value> = match default.as_sequence() {
None => {
log::warn!("No default tasks have been found");
vec![].to_vec()
}
Some(defaults) => defaults.to_vec(),
};

let task_list: Vec<Value> = match tasks.as_sequence() {
None => {
log::warn!("No tasks have been found");
vec![].to_vec()
}
Some(tasks) => tasks.to_vec(),
};

if task_list.is_empty() || default_tasks.is_empty() {
log::warn!("The default task list and main task list have to be defined");
return Ok(Workflow {
name: "invalid".to_string(),
tasks: vec![],
default: vec![],
});
}

for def in default_tasks.iter() {
let default_task_name = def.as_str().unwrap().to_string();

for task in task_list.iter() {
let task_name = &task.as_mapping().unwrap()["name"]
.as_str()
.unwrap()
.to_string();

// Check if the default task name matches a task name in the task list
if task_name.eq(&default_task_name) {
let commands = task["cmds"].as_sequence().unwrap();
let commands_as_str: Vec<String> = commands
.iter()
.map(|c| {
let value = c.as_str();
String::from(value.unwrap())
})
.collect();

workflow_tasks.push(
TaskBuilder::new(String::from(task["name"].as_str().unwrap()))
.commands(commands_as_str)
.build(),
)
}
}
}

let workflow = WorkflowBuilder::new(workflow_name.as_str().unwrap().to_string())
Expand All @@ -106,13 +165,15 @@ impl Workflow {
#[derive(Serialize, Deserialize, Default, Debug)]
pub struct WorkflowBuilder {
name: String,
default: Vec<String>,
tasks: Vec<Task>,
}

impl WorkflowBuilder {
pub fn new(name: String) -> WorkflowBuilder {
WorkflowBuilder {
name,
default: vec![],
tasks: vec![],
}
}
Expand All @@ -127,9 +188,15 @@ impl WorkflowBuilder {
self
}

pub fn add_defaults(mut self, task_names: Vec<String>) -> WorkflowBuilder {
self.default = task_names;
self
}

pub fn build(self) -> Workflow {
Workflow {
name: self.name,
default: self.default,
tasks: self.tasks,
}
}
Expand All @@ -143,6 +210,7 @@ mod tests {
fn get_expected_workflow() -> Workflow {
Workflow {
name: "my workflow".to_string(),
default: vec!["sample task1".to_string(), "sample task2".to_string()],
tasks: vec![
Task {
name: "sample task1".to_string(),
Expand All @@ -168,6 +236,7 @@ mod tests {
.build();

let workflow = WorkflowBuilder::new("my workflow".to_string())
.add_defaults(vec![task1.name.clone(), task2.name.clone()])
.add_task(task1)
.add_task(task2)
.build();
Expand All @@ -186,6 +255,7 @@ mod tests {
.add_command("echo hello world".to_string())
.build();
let workflow = WorkflowBuilder::new("my workflow".to_string())
.add_defaults(vec![task1.name.clone(), task2.name.clone()])
.add_tasks(vec![task1, task2])
.build();

Expand Down

0 comments on commit 25c9692

Please sign in to comment.