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:
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();