Skip to content

Commit

Permalink
adds shell runner
Browse files Browse the repository at this point in the history
  • Loading branch information
reederc42 committed Jun 6, 2024
1 parent 7af5069 commit eb64bb0
Show file tree
Hide file tree
Showing 7 changed files with 187 additions and 160 deletions.
133 changes: 8 additions & 125 deletions ci/src/docker.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
use std::process::Command;

use sha2::{Digest, Sha256};

use crate::*;

// Latest postgres image: https://hub.docker.com/_/postgres/tags
Expand All @@ -11,8 +9,6 @@ pub struct Docker {
pub context: Rc<Context>,
}

const CMD_HASH_LENGTH: usize = 7;

impl Docker {
fn build_docker_run_args(&self, background: bool, context: ExecutionContext, env: Vec<&str>, include_source: bool, cmd: Vec<&str>, remove: bool) -> Vec<String> {
let mut args: Vec<String> = vec![
Expand Down Expand Up @@ -65,35 +61,10 @@ impl Docker {

let mut finished_print = None;
if self.context.verbose {
finished_print = Some(print_command(cmd, false));
finished_print = Some(shell::print_command(cmd, false));
}

let res = cmd.spawn();

match res {
Ok(mut c) => {
let res = c.wait();
if let Some(f) = finished_print {
f();
}
match res {
Ok(s) => {
match s.code() {
Some(code) => {
if code != 0 {
Err(error!("Received non-zero exit status: {}", code))
} else {
Ok(())
}
},
None => Err(error!("Process terminated with signal")),
}
},
Err(e) => Err(Box::new(e)),
}
},
Err(e) => Err(Box::new(e)),
}
shell::spawn_result_to_result(cmd.spawn(), finished_print)
}

fn pull_postgres_image(&self, image: &str) -> Result<(), Error> {
Expand All @@ -105,39 +76,14 @@ impl Docker {

let mut finished_print = None;
if self.context.verbose {
finished_print = Some(print_command(cmd, false));
finished_print = Some(shell::print_command(cmd, false));
}

let res = cmd.spawn();

match res {
Ok(mut c) => {
let res = c.wait();
if let Some(f) = finished_print {
f();
}
match res {
Ok(s) => {
match s.code() {
Some(code) => {
if code != 0 {
Err(error!("Received non-zero exit status: {}", code))
} else {
Ok(())
}
},
None => Err(error!("Process terminated with signal")),
}
},
Err(e) => Err(Box::new(e)),
}
},
Err(e) => Err(Box::new(e)),
}
shell::spawn_result_to_result(cmd.spawn(), finished_print)
}
}

impl Builder for Docker {
impl Runner for Docker {
fn build(&self, exec_context: ExecutionContext, build_context: &Context) -> Result<(), Error> {
match exec_context {
ExecutionContext::Build => {
Expand All @@ -157,9 +103,7 @@ impl Builder for Docker {
ExecutionContext::Postgres => self.pull_postgres_image(POSTGRES_IMAGE),
}
}
}

impl Runner for Docker {
fn run(&self, context: ExecutionContext, env: Vec<&str>, include_source: bool, cmd: Vec<&str>) -> Result<(), Error> {
let args = self.build_docker_run_args(false, context, env, include_source, cmd, true);

Expand All @@ -168,35 +112,10 @@ impl Runner for Docker {

let mut finished_print = None;
if self.context.verbose {
finished_print = Some(print_command(cmd, false));
finished_print = Some(shell::print_command(cmd, false));
}

let res = cmd.spawn();

match res {
Ok(mut c) => {
let res = c.wait();
if let Some(f) = finished_print {
f();
}
match res{
Ok(s) => {
match s.code() {
Some(code) => {
if code != 0 {
Err(error!("Received non-zero exit status: {}", code))
} else {
Ok(())
}
},
None => Err(error!("Process terminated with signal")),
}
},
Err(e) => Err(Box::new(e)),
}
},
Err(e) => Err(Box::new(e)),
}
shell::spawn_result_to_result(cmd.spawn(), finished_print)
}

fn run_background(&self, context: ExecutionContext, env: Vec<&str>, include_source: bool, cmd: Vec<&str>) -> Result<Box<dyn BackgroundServer>, Error> {
Expand All @@ -207,7 +126,7 @@ impl Runner for Docker {

let mut finished_print = None;
if self.context.verbose {
finished_print = Some(print_command(cmd, true));
finished_print = Some(shell::print_command(cmd, true));
}

let output = cmd.output();
Expand Down Expand Up @@ -287,39 +206,3 @@ impl BackgroundServer for DockerBackgroundServer {
)
}
}

fn print_command(cmd: &Command, background: bool) -> Box<dyn FnOnce()> {
let program = cmd.get_program().to_string_lossy();

let full_cmd = format!(
"{} {}",
program,
cmd.get_args()
.map(|a| a.to_string_lossy())
.collect::<Vec<_>>()
.join(" "),
);

let cmd_hash: String = format!("{:x}", Sha256::digest(&full_cmd))
.chars()
.take(CMD_HASH_LENGTH)
.collect();

let id = format!("{}-{}", program, cmd_hash);

if background {
println!("Executing background command [id: {}]:\n```", id);
} else {
println!("Executing command [id: {}]:\n```", id);
}
println!("{}", full_cmd);
println!("```");

Box::new(move || {
if background {
println!("Background command completed [id: {}]", id);
} else {
println!("Command completed [id: {}]", id);
}
})
}
35 changes: 18 additions & 17 deletions ci/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::{fs, rc::Rc};
use clap::Parser;

mod docker;
mod shell;
mod stages;

#[macro_export]
Expand Down Expand Up @@ -37,8 +38,13 @@ pub struct Cli {
#[arg(short, long)]
verbose: bool,

/// Fail on first stage error
#[arg(short, long)]
fail_fast: bool,

/// Runner for scripts [docker, shell]
#[arg(short, long, default_value = "docker")]
runner: String,
}

pub fn cmd(args: Cli) {
Expand All @@ -63,12 +69,15 @@ pub fn cmd(args: Cli) {
),
verbose: args.verbose,
});
let docker = Rc::new(docker::Docker{
context: context.clone(),
});
let config = Config {
runner: docker.clone(),
builder: docker.clone(),

let runner: Box<dyn Runner> = match args.runner.as_str() {
"docker" => Box::new(docker::Docker {
context: context.clone(),
}),
"shell" => Box::new(shell::Shell {
context: context.clone(),
}),
r => panic!("Invalid runner option: {}", r),
};

match fs::remove_dir_all(TEST_RESULTS_DIR) {
Expand All @@ -91,7 +100,7 @@ pub fn cmd(args: Cli) {
println!("::group::Stage: {}", s.name());
}

if let Err(e) = s.run(&context, &config) {
if let Err(e) = s.run(&context, &runner) {
println!("Stage error: {:?}", e);
stages_failed += 1;
if args.fail_fast {
Expand Down Expand Up @@ -136,16 +145,12 @@ pub struct Context {
pub verbose: bool,
}

pub struct Config {
pub runner: Rc<dyn Runner>,
pub builder: Rc<dyn Builder>,
}

pub trait BackgroundServer {
fn addr(&self) -> String;
}

pub trait Runner {
fn build(&self, exec_context: ExecutionContext, build_context: &Context) -> Result<(), Error>;
fn run(&self, context: ExecutionContext, env: Vec<&str>, include_source: bool, cmd: Vec<&str>) -> Result<(), Error>;
fn run_background(&self, context: ExecutionContext, env: Vec<&str>, include_source: bool, cmd: Vec<&str>) -> Result<Box<dyn BackgroundServer>, Error>;
}
Expand All @@ -156,11 +161,7 @@ pub enum ExecutionContext {
Postgres,
}

pub trait Builder {
fn build(&self, exec_context: ExecutionContext, build_context: &Context) -> Result<(), Error>;
}

pub trait Stage {
fn name(&self) -> &'static str;
fn run(&self, context: &Context, config: &Config) -> Result<(), Error>;
fn run(&self, context: &Context, runner: &Box<dyn Runner>) -> Result<(), Error>;
}
Loading

0 comments on commit eb64bb0

Please sign in to comment.