cinderella

[unmaintained] simple CI engine
Log | Files | Refs | README | LICENSE

commit 1531b5fa2ce8a2626a5d5505dcadc20297064597
parent ea242283dd84bfdb99b4ada52b66555583e4cda5
Author: Stefan Koch <programming@stefan-koch.name>
Date:   Sun, 15 Sep 2019 19:40:25 +0200

add a conditional build trigger to pipelines

Diffstat:
M.cinderella.toml | 1+
MREADME.md | 15+++++++++++++++
Msrc/execution.rs | 37+++++++++++++++++++++++++++++++------
Msrc/pipeline.rs | 24+++++++++++++-----------
4 files changed, 60 insertions(+), 17 deletions(-)

diff --git a/.cinderella.toml b/.cinderella.toml @@ -11,3 +11,4 @@ commands = [ "rm -f /opt/cinderella/cinderella-{{ branch }}", "mv /opt/cinderella/.cinderella-{{ branch }} /opt/cinderella/cinderella-{{ branch }}", ] +when = "'{{ branch }}' == 'master'" diff --git a/README.md b/README.md @@ -46,3 +46,18 @@ substituted with actual values from the build context. Currently supported variables are: - `{{ branch }}`: The name of the branch that is built + +You can conditionally execute a pipeline with the `when` option, for example +to run a pipeline only for specific branches: + +```toml +[build-release] +commands = [ + "cargo build --release", +] +when = "'{{ branch }}' == 'master'" +``` + +The condition will be executed with the Linux `test` command. Please be aware +that this behaviour will likely change in the future and another test +execution engine might be used. diff --git a/src/execution.rs b/src/execution.rs @@ -6,7 +6,17 @@ use crate::pipeline; pub fn execute(pipelines: &Vec<pipeline::Pipeline>, variables: &HashMap<String, String>) { for pipeline in pipelines { - execute_pipeline(pipeline, &variables); + let execute = match &pipeline.when { + Some(when) => { + let test = replace_variables(&when, &variables); + execute_test(&test) + } + None => true, + }; + + if execute { + execute_pipeline(pipeline, &variables); + } } } @@ -20,11 +30,7 @@ pub fn execute_pipeline(pipeline: &pipeline::Pipeline, let cmd = replace_variables(&cmd, &variables); // TODO: Raise error if some variables remain unsubstituted? - // TODO: Successful argument parsing needs a lot more details, - // e.g. for quoted arguments like myprogram "argument 1" - // but for a first shot this works - let parts: Vec<&str> = cmd.split(" ").collect(); - + let parts = split_command(&cmd); let status = Command::new(parts[0]) .args(&parts[1..]) .status() @@ -34,6 +40,25 @@ pub fn execute_pipeline(pipeline: &pipeline::Pipeline, } } +fn split_command<'a>(command: &'a str) -> Vec<&'a str> { + // TODO: Successful argument parsing needs a lot more details, + // e.g. for quoted arguments like myprogram "argument 1" + // but for a first shot this works + let parts: Vec<&str> = command.split(" ").collect(); + parts +} + +fn execute_test(test: &str) -> bool { + let args = split_command(&test); + + let status = Command::new("test") + .args(&args) + .status() + .expect(&format!("failed to run test {}", test)); + + status.success() +} + fn replace_variables(command: &str, variables: &HashMap<String, String>) -> String { diff --git a/src/pipeline.rs b/src/pipeline.rs @@ -6,6 +6,7 @@ use toml::Value; pub struct Pipeline { pub name: String, pub commands: Vec<String>, + pub when: Option<String>, } pub fn load_pipeline(path: &PathBuf) -> Option<Vec<Pipeline>> { @@ -14,17 +15,18 @@ pub fn load_pipeline(path: &PathBuf) -> Option<Vec<Pipeline>> { let res: Vec<Pipeline> = data.as_table().unwrap().iter() .filter_map(|(key, value)| { - if value.is_table() { - // TODO: Better handle unwrap here and return error when - // file is invalid - Some(Pipeline { - name: key.to_string(), - commands: value["commands"].as_array().unwrap().iter() - .map(|cmd| String::from(cmd.as_str().unwrap())) - .collect(), - }) - } else { - None + match value { + Value::Table(table) => { + // TODO: Better error handling needed + Some(Pipeline { + name: key.to_string(), + commands: value["commands"].as_array().unwrap().iter() + .map(|cmd| String::from(cmd.as_str().unwrap())) + .collect(), + when: table.get("when").map(|v| String::from(v.as_str().unwrap())), + }) + }, + _ => None } }).collect();