diff --git a/CHANGELOG.md b/CHANGELOG.md index a8966107..d1105e86 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## CHANGELOG +### v0.37.8 + +* Enhancement: Support script runners and shebang in condition scripts #987 + ### v0.37.7 (2024-01-14) * Fix: Detect crate installation fix for new cargo list format diff --git a/examples/condition.toml b/examples/condition.toml index ef4b4450..83b28872 100755 --- a/examples/condition.toml +++ b/examples/condition.toml @@ -116,3 +116,17 @@ condition = { files_modified = { input = [ ] } } command = "cargo" args = ["build"] + +[tasks.test-duckscript-condition] +condition_script = [''' +#!@duckscript + +var = set "hello from duckscript" +echo ${var} +echo %{var} + +exit 0 +'''] +script = ''' +echo "duckscript condition was met" +''' diff --git a/src/lib/condition.rs b/src/lib/condition.rs index c33de7d3..1bd7005e 100755 --- a/src/lib/condition.rs +++ b/src/lib/condition.rs @@ -7,11 +7,11 @@ #[path = "condition_test.rs"] mod condition_test; -use crate::command; use crate::environment; use crate::profile; +use crate::scriptengine; use crate::types; -use crate::types::{FlowInfo, RustVersionCondition, Step, TaskCondition}; +use crate::types::{FlowInfo, RustVersionCondition, ScriptValue, Step, TaskCondition}; use crate::version::{is_newer, is_same}; use envmnt; use fsio; @@ -438,14 +438,14 @@ fn validate_script(condition_script: &Option>, script_runner: Option Some(ref script) => { debug!("Checking task condition script."); - let exit_code = - command::run_script_get_exit_code(&script, script_runner, &vec![], false); - - if exit_code == 0 { - true - } else { - false - } + return scriptengine::invoke_script_pre_flow( + &ScriptValue::Text(script.to_vec()), + script_runner, + None, + None, + false, + &vec![], + ); } None => true, } diff --git a/src/lib/condition_test.rs b/src/lib/condition_test.rs index 4d869de1..9f63f07c 100755 --- a/src/lib/condition_test.rs +++ b/src/lib/condition_test.rs @@ -877,6 +877,20 @@ fn validate_script_invalid() { assert!(!enabled); } +#[test] +fn validate_script_valid_with_duckscript_shebang() { + let enabled = validate_script(&Some(vec!["#!@duckscript\nexit 0".to_string()]), None); + + assert!(enabled); +} + +#[test] +fn validate_script_invalid_with_duckscript_shebang() { + let enabled = validate_script(&Some(vec!["#!@duckscript\nexit 1".to_string()]), None); + + assert!(!enabled); +} + #[test] #[ignore] fn validate_profile_valid() { diff --git a/src/lib/scriptengine/duck_script/mod.rs b/src/lib/scriptengine/duck_script/mod.rs index 3de19c0b..33508cd1 100644 --- a/src/lib/scriptengine/duck_script/mod.rs +++ b/src/lib/scriptengine/duck_script/mod.rs @@ -27,7 +27,7 @@ pub(crate) fn execute( flow_info: Option<&FlowInfo>, flow_state: Option>>, validate: bool, -) { +) -> bool { let mut array_command = "@ = array".to_string(); let mut index = 0; for _ in cli_arguments { @@ -59,6 +59,8 @@ pub(crate) fn execute( if validate { error!("Error while running duckscript: {}", error); } + + return false; } }; @@ -66,13 +68,17 @@ pub(crate) fn execute( if !directory.is_empty() { environment::setup_cwd(Some(&directory)); } + + true } Err(error) => { if validate { error!("Unable to load duckscript SDK: {}", error); } + + false } - }; + } } pub(crate) fn create_common_context(cli_arguments: &Vec) -> Context { diff --git a/src/lib/scriptengine/duck_script/mod_test.rs b/src/lib/scriptengine/duck_script/mod_test.rs index bb6b457f..5434ab32 100644 --- a/src/lib/scriptengine/duck_script/mod_test.rs +++ b/src/lib/scriptengine/duck_script/mod_test.rs @@ -5,24 +5,26 @@ use envmnt; #[test] fn execute_duckscript() { - execute( + let valid = execute( &vec!["echo test".to_string()], &vec![], Some(&test::create_empty_flow_info()), Some(Rc::new(RefCell::new(FlowState::new()))), true, ); + assert!(valid); } #[test] fn execute_duckscript_error_no_validate() { - execute( + let valid = execute( &vec!["badcommand".to_string()], &vec![], Some(&test::create_empty_flow_info()), Some(Rc::new(RefCell::new(FlowState::new()))), false, ); + assert!(!valid); } #[test] @@ -39,13 +41,14 @@ fn execute_duckscript_error_with_validate() { #[test] fn execute_duckscript_cli_arguments() { - execute( + let valid = execute( &vec!["assert ${1}".to_string()], &vec!["true".to_string()], Some(&test::create_empty_flow_info()), Some(Rc::new(RefCell::new(FlowState::new()))), true, ); + assert!(valid); } #[test] diff --git a/src/lib/scriptengine/generic_script.rs b/src/lib/scriptengine/generic_script.rs index c296e7d8..3ae49202 100644 --- a/src/lib/scriptengine/generic_script.rs +++ b/src/lib/scriptengine/generic_script.rs @@ -39,7 +39,7 @@ pub(crate) fn execute( arguments: Option>, cli_arguments: &Vec, validate: bool, -) { +) -> bool { let file = create_script_file(script_text, &extension); let valid = run_file(&file, &runner, arguments, &mut cli_arguments.clone()); @@ -49,4 +49,6 @@ pub(crate) fn execute( if validate && !valid { error!("Unable to execute script."); } + + return valid; } diff --git a/src/lib/scriptengine/generic_script_test.rs b/src/lib/scriptengine/generic_script_test.rs index 8580633f..9878bb49 100644 --- a/src/lib/scriptengine/generic_script_test.rs +++ b/src/lib/scriptengine/generic_script_test.rs @@ -3,7 +3,7 @@ use crate::test; #[test] fn execute_shell() { - execute( + let valid = execute( &vec!["exit 0".to_string()], test::get_os_runner(), test::get_os_extension(), @@ -11,6 +11,7 @@ fn execute_shell() { &vec![], true, ); + assert!(valid); } #[test] @@ -28,7 +29,7 @@ fn execute_shell_error() { #[test] fn execute_shell_error_no_validate() { - execute( + let valid = execute( &vec!["exit 1".to_string()], test::get_os_runner(), test::get_os_extension(), @@ -36,11 +37,12 @@ fn execute_shell_error_no_validate() { &vec![], false, ); + assert!(!valid); } #[test] fn execute_shell_empty_arguments() { - execute( + let valid = execute( &vec!["exit 0".to_string()], test::get_os_runner(), test::get_os_extension(), @@ -48,12 +50,13 @@ fn execute_shell_empty_arguments() { &vec![], true, ); + assert!(valid); } #[test] #[cfg(target_os = "linux")] fn execute_shell_cli_arguments() { - execute( + let valid = execute( &vec!["exit $1".to_string()], test::get_os_runner(), test::get_os_extension(), @@ -61,6 +64,7 @@ fn execute_shell_cli_arguments() { &vec!["0".to_string()], true, ); + assert!(valid); } #[test] diff --git a/src/lib/scriptengine/mod.rs b/src/lib/scriptengine/mod.rs index 863d2103..b28710f9 100755 --- a/src/lib/scriptengine/mod.rs +++ b/src/lib/scriptengine/mod.rs @@ -261,27 +261,19 @@ fn invoke_script( match engine_type { EngineType::OS => { let script_text = get_script_text(script); - os_script::execute(&script_text, script_runner, cli_arguments, validate); - - true + os_script::execute(&script_text, script_runner, cli_arguments, validate) } EngineType::Duckscript => { let script_text = get_script_text(script); - duck_script::execute(&script_text, cli_arguments, flow_info, flow_state, validate); - - true + duck_script::execute(&script_text, cli_arguments, flow_info, flow_state, validate) } EngineType::Rust => { let script_text = get_script_text(script); - rsscript::execute(&script_text, cli_arguments, validate); - - true + rsscript::execute(&script_text, cli_arguments, validate) } EngineType::Shell2Batch => { let script_text = get_script_text(script); - shell_to_batch::execute(&script_text, cli_arguments, validate); - - true + shell_to_batch::execute(&script_text, cli_arguments, validate) } EngineType::Generic => { let script_text = get_script_text(script); @@ -293,16 +285,12 @@ fn invoke_script( script_runner_args.clone(), cli_arguments, validate, - ); - - true + ) } EngineType::Shebang => { let script_text = get_script_text(script); let extension = script_extension.clone(); - shebang_script::execute(&script_text, &extension, cli_arguments, validate); - - true + shebang_script::execute(&script_text, &extension, cli_arguments, validate) } EngineType::Unsupported => false, } diff --git a/src/lib/scriptengine/os_script.rs b/src/lib/scriptengine/os_script.rs index 4a8c12ad..205b5924 100644 --- a/src/lib/scriptengine/os_script.rs +++ b/src/lib/scriptengine/os_script.rs @@ -14,6 +14,8 @@ pub(crate) fn execute( runner: Option, cli_arguments: &Vec, validate: bool, -) { - command::run_script_get_exit_code(&script_text, runner, &cli_arguments, validate); +) -> bool { + let exit_code = + command::run_script_get_exit_code(&script_text, runner, &cli_arguments, validate); + exit_code == 0 } diff --git a/src/lib/scriptengine/os_script_test.rs b/src/lib/scriptengine/os_script_test.rs index b12d97b4..b61dd80a 100644 --- a/src/lib/scriptengine/os_script_test.rs +++ b/src/lib/scriptengine/os_script_test.rs @@ -8,12 +8,13 @@ fn execute_shell() { #[test] fn execute_shell_with_runner() { - execute( + let valid = execute( &vec!["exit 0".to_string()], Some(test::get_os_runner()), &vec![], true, ); + assert!(valid); } #[test] @@ -24,5 +25,6 @@ fn execute_shell_error() { #[test] fn execute_shell_error_no_validate() { - execute(&vec!["exit 1".to_string()], None, &vec![], false); + let valid = execute(&vec!["exit 1".to_string()], None, &vec![], false); + assert!(!valid); } diff --git a/src/lib/scriptengine/rsscript.rs b/src/lib/scriptengine/rsscript.rs index e150ec64..65fe8e23 100755 --- a/src/lib/scriptengine/rsscript.rs +++ b/src/lib/scriptengine/rsscript.rs @@ -101,7 +101,11 @@ fn run_file(file: &str, cli_arguments: &Vec, provider: &ScriptRunner) -> exit_code == 0 } -pub(crate) fn execute(rust_script: &Vec, cli_arguments: &Vec, validate: bool) { +pub(crate) fn execute( + rust_script: &Vec, + cli_arguments: &Vec, + validate: bool, +) -> bool { let provider = get_script_runner(); install_crate(&provider); @@ -113,4 +117,6 @@ pub(crate) fn execute(rust_script: &Vec, cli_arguments: &Vec, va if validate && !valid { error!("Unable to execute rust code."); } + + return valid; } diff --git a/src/lib/scriptengine/rsscript_test.rs b/src/lib/scriptengine/rsscript_test.rs index 6d4e5a5a..96a6af7d 100755 --- a/src/lib/scriptengine/rsscript_test.rs +++ b/src/lib/scriptengine/rsscript_test.rs @@ -56,11 +56,12 @@ fn execute_default_valid() { if test::should_test(false) { envmnt::remove("CARGO_MAKE_RUST_SCRIPT_PROVIDER"); - execute( + let valid = execute( &vec!["fn main() {println!(\"test\");}".to_string()], &vec![], true, ); + assert!(valid); } } @@ -104,11 +105,12 @@ fn execute_default_runtime_panic_no_validate() { if test::should_test(false) { envmnt::remove("CARGO_MAKE_RUST_SCRIPT_PROVIDER"); - execute( + let valid = execute( &vec!["fn main() {panic!(\"error\");}".to_string()], &vec![], false, ); + assert!(!valid); envmnt::remove("CARGO_MAKE_RUST_SCRIPT_PROVIDER"); } @@ -120,11 +122,12 @@ fn execute_rust_script_valid() { if test::should_test(false) { envmnt::set("CARGO_MAKE_RUST_SCRIPT_PROVIDER", "rust-script"); - execute( + let valid = execute( &vec!["fn main() {println!(\"test\");}".to_string()], &vec![], true, ); + assert!(valid); envmnt::remove("CARGO_MAKE_RUST_SCRIPT_PROVIDER"); } @@ -170,11 +173,12 @@ fn execute_rust_script_runtime_panic_no_validate() { if test::should_test(false) { envmnt::set("CARGO_MAKE_RUST_SCRIPT_PROVIDER", "rust-script"); - execute( + let valid = execute( &vec!["fn main() {panic!(\"error\");}".to_string()], &vec![], false, ); + assert!(!valid); envmnt::remove("CARGO_MAKE_RUST_SCRIPT_PROVIDER"); } @@ -220,11 +224,12 @@ fn execute_cargo_play_runtime_panic_no_validate() { if test::should_test(false) { envmnt::set("CARGO_MAKE_RUST_SCRIPT_PROVIDER", "cargo-play"); - execute( + let valid = execute( &vec!["fn main() {panic!(\"error\");}".to_string()], &vec![], false, ); + assert!(!valid); envmnt::remove("CARGO_MAKE_RUST_SCRIPT_PROVIDER"); } diff --git a/src/lib/scriptengine/shebang_script.rs b/src/lib/scriptengine/shebang_script.rs index b48e80be..5f75e579 100644 --- a/src/lib/scriptengine/shebang_script.rs +++ b/src/lib/scriptengine/shebang_script.rs @@ -105,7 +105,7 @@ pub(crate) fn execute( extension: &Option, cli_arguments: &Vec, validate: bool, -) { +) -> bool { let shebang = get_shebang(&script_text); match shebang.runner { @@ -122,12 +122,14 @@ pub(crate) fn execute( shebang.arguments, &cli_arguments, validate, - ); + ) } None => { if validate { error!("Unable to execute script using shebang."); } + + false } - }; + } } diff --git a/src/lib/scriptengine/shebang_script_test.rs b/src/lib/scriptengine/shebang_script_test.rs index 22197fe9..92050b6d 100644 --- a/src/lib/scriptengine/shebang_script_test.rs +++ b/src/lib/scriptengine/shebang_script_test.rs @@ -86,12 +86,13 @@ fn get_shebang_single_command_with_spaces_before_shebang() { #[test] #[cfg(target_os = "linux")] fn execute_sh() { - execute( + let valid = execute( &vec!["#! sh".to_string(), "exit $1".to_string()], &None, &vec!["0".to_string()], true, ); + assert!(valid); } #[test] diff --git a/src/lib/scriptengine/shell_to_batch.rs b/src/lib/scriptengine/shell_to_batch.rs index f24701a8..fdc8e8d1 100755 --- a/src/lib/scriptengine/shell_to_batch.rs +++ b/src/lib/scriptengine/shell_to_batch.rs @@ -10,8 +10,8 @@ mod shell_to_batch_test; use crate::command; use shell2batch; -pub(crate) fn execute(script: &Vec, cli_arguments: &Vec, validate: bool) { - if cfg!(windows) { +pub(crate) fn execute(script: &Vec, cli_arguments: &Vec, validate: bool) -> bool { + let exit_code = if cfg!(windows) { let shell_script = script.join("\n"); let windows_batch = shell2batch::convert(&shell_script); @@ -20,8 +20,10 @@ pub(crate) fn execute(script: &Vec, cli_arguments: &Vec, validat .map(|string| string.to_string()) .collect(); - command::run_script_get_exit_code(&windows_script_lines, None, cli_arguments, validate); + command::run_script_get_exit_code(&windows_script_lines, None, cli_arguments, validate) } else { - command::run_script_get_exit_code(script, None, cli_arguments, validate); + command::run_script_get_exit_code(script, None, cli_arguments, validate) }; + + exit_code == 0 } diff --git a/src/lib/scriptengine/shell_to_batch_test.rs b/src/lib/scriptengine/shell_to_batch_test.rs index aaa1abb5..5f0f129a 100755 --- a/src/lib/scriptengine/shell_to_batch_test.rs +++ b/src/lib/scriptengine/shell_to_batch_test.rs @@ -2,11 +2,13 @@ use super::*; #[test] fn execute_valid() { - execute( + let valid = execute( &vec!["echo test".to_string()], &vec!["test".to_string()], true, ); + + assert!(valid); } #[test] @@ -17,5 +19,6 @@ fn execute_error() { #[test] fn execute_error_no_validate() { - execute(&vec!["exit 1".to_string()], &vec![], false); + let valid = execute(&vec!["exit 1".to_string()], &vec![], false); + assert!(!valid); }