style: apply cargo fmt workspace-wide
Pure formatting pass from `cargo fmt --all`. No logic changes. Separating this out so the 1.9 release feature commits that follow show only their intentional edits.
This commit is contained in:
@@ -221,7 +221,10 @@ workflow:
|
||||
let test_config: wfe_yaml::executors::shell::ShellConfig =
|
||||
serde_json::from_value(test_step.step_config.clone().unwrap()).unwrap();
|
||||
assert_eq!(test_config.run, "cargo build");
|
||||
assert_eq!(test_config.shell, "bash", "shell should be inherited from YAML anchor alias");
|
||||
assert_eq!(
|
||||
test_config.shell, "bash",
|
||||
"shell should be inherited from YAML anchor alias"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -473,8 +476,14 @@ workflow:
|
||||
"#;
|
||||
let result = load_single_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_err());
|
||||
let err = match result { Err(e) => e.to_string(), Ok(_) => panic!("expected error") };
|
||||
assert!(err.contains("explode"), "Error should mention the invalid type, got: {err}");
|
||||
let err = match result {
|
||||
Err(e) => e.to_string(),
|
||||
Ok(_) => panic!("expected error"),
|
||||
};
|
||||
assert!(
|
||||
err.contains("explode"),
|
||||
"Error should mention the invalid type, got: {err}"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -517,7 +526,10 @@ workflow:
|
||||
.iter()
|
||||
.find(|s| s.name.as_deref() == Some(*child_name))
|
||||
.unwrap();
|
||||
assert!(child.step_config.is_some(), "Child {child_name} should have step_config");
|
||||
assert!(
|
||||
child.step_config.is_some(),
|
||||
"Child {child_name} should have step_config"
|
||||
);
|
||||
}
|
||||
|
||||
// Factories should include entries for all 3 children.
|
||||
@@ -806,7 +818,10 @@ workflow:
|
||||
"#;
|
||||
let result = load_single_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_err());
|
||||
let err = match result { Err(e) => e.to_string(), Ok(_) => panic!("expected error") };
|
||||
let err = match result {
|
||||
Err(e) => e.to_string(),
|
||||
Ok(_) => panic!("expected error"),
|
||||
};
|
||||
assert!(
|
||||
err.contains("config"),
|
||||
"Error should mention missing config, got: {err}"
|
||||
@@ -1019,11 +1034,11 @@ workflow:
|
||||
/// SubWorkflowStep (from wfe-core), not a placeholder.
|
||||
#[tokio::test]
|
||||
async fn workflow_step_factory_produces_real_sub_workflow_step() {
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
use std::sync::Mutex;
|
||||
use wfe_core::models::{ExecutionPointer, WorkflowInstance, WorkflowStep as WfStep};
|
||||
use wfe_core::traits::step::{HostContext, StepExecutionContext};
|
||||
use std::pin::Pin;
|
||||
use std::future::Future;
|
||||
use std::sync::Mutex;
|
||||
|
||||
let yaml = r#"
|
||||
workflows:
|
||||
@@ -1047,30 +1062,45 @@ workflows:
|
||||
let workflows = load_workflow_from_str(yaml, &config).unwrap();
|
||||
|
||||
// Find the parent workflow's factory for the "run-child" step
|
||||
let parent = workflows.iter().find(|w| w.definition.id == "parent").unwrap();
|
||||
let factory_key = parent.step_factories.iter()
|
||||
let parent = workflows
|
||||
.iter()
|
||||
.find(|w| w.definition.id == "parent")
|
||||
.unwrap();
|
||||
let factory_key = parent
|
||||
.step_factories
|
||||
.iter()
|
||||
.find(|(k, _)| k.contains("run-child"))
|
||||
.map(|(k, _)| k.clone())
|
||||
.expect("run-child factory should exist");
|
||||
|
||||
// Create a step from the factory
|
||||
let factory = &parent.step_factories.iter()
|
||||
let factory = &parent
|
||||
.step_factories
|
||||
.iter()
|
||||
.find(|(k, _)| *k == factory_key)
|
||||
.unwrap().1;
|
||||
.unwrap()
|
||||
.1;
|
||||
let mut step = factory();
|
||||
|
||||
// Mock host context that records the start_workflow call
|
||||
struct MockHost { called: Mutex<bool> }
|
||||
struct MockHost {
|
||||
called: Mutex<bool>,
|
||||
}
|
||||
impl HostContext for MockHost {
|
||||
fn start_workflow(&self, _def: &str, _ver: u32, _data: serde_json::Value)
|
||||
-> Pin<Box<dyn Future<Output = wfe_core::Result<String>> + Send + '_>>
|
||||
{
|
||||
fn start_workflow(
|
||||
&self,
|
||||
_def: &str,
|
||||
_ver: u32,
|
||||
_data: serde_json::Value,
|
||||
) -> Pin<Box<dyn Future<Output = wfe_core::Result<String>> + Send + '_>> {
|
||||
*self.called.lock().unwrap() = true;
|
||||
Box::pin(async { Ok("child-instance-id".to_string()) })
|
||||
}
|
||||
}
|
||||
|
||||
let host = MockHost { called: Mutex::new(false) };
|
||||
let host = MockHost {
|
||||
called: Mutex::new(false),
|
||||
};
|
||||
let pointer = ExecutionPointer::new(0);
|
||||
let wf_step = WfStep::new(0, &factory_key);
|
||||
let workflow = WorkflowInstance::new("parent", 1, serde_json::json!({}));
|
||||
@@ -1182,15 +1212,13 @@ workflow:
|
||||
}
|
||||
// Second child: not
|
||||
match &children[1] {
|
||||
wfe_core::models::StepCondition::Not(inner) => {
|
||||
match inner.as_ref() {
|
||||
wfe_core::models::StepCondition::Comparison(cmp) => {
|
||||
assert_eq!(cmp.field, ".inputs.skip");
|
||||
assert_eq!(cmp.operator, wfe_core::models::ComparisonOp::Equals);
|
||||
}
|
||||
other => panic!("Expected Comparison inside Not, got: {other:?}"),
|
||||
wfe_core::models::StepCondition::Not(inner) => match inner.as_ref() {
|
||||
wfe_core::models::StepCondition::Comparison(cmp) => {
|
||||
assert_eq!(cmp.field, ".inputs.skip");
|
||||
assert_eq!(cmp.operator, wfe_core::models::ComparisonOp::Equals);
|
||||
}
|
||||
}
|
||||
other => panic!("Expected Comparison inside Not, got: {other:?}"),
|
||||
},
|
||||
other => panic!("Expected Not, got: {other:?}"),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ fn make_context<'a>(
|
||||
workflow,
|
||||
cancellation_token: tokio_util::sync::CancellationToken::new(),
|
||||
host_context: None,
|
||||
log_sink: None,
|
||||
log_sink: None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,10 +224,7 @@ workflow:
|
||||
let result = wfe_yaml::load_single_workflow_from_str(yaml, &config);
|
||||
assert!(result.is_err());
|
||||
let msg = result.err().unwrap().to_string();
|
||||
assert!(
|
||||
msg.contains("config") || msg.contains("Deno"),
|
||||
"got: {msg}"
|
||||
);
|
||||
assert!(msg.contains("config") || msg.contains("Deno"), "got: {msg}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -247,10 +244,7 @@ workflow:
|
||||
let result = wfe_yaml::load_single_workflow_from_str(yaml, &config);
|
||||
assert!(result.is_err());
|
||||
let msg = result.err().unwrap().to_string();
|
||||
assert!(
|
||||
msg.contains("script") || msg.contains("file"),
|
||||
"got: {msg}"
|
||||
);
|
||||
assert!(msg.contains("script") || msg.contains("file"), "got: {msg}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -269,7 +263,10 @@ workflow:
|
||||
let compiled = wfe_yaml::load_single_workflow_from_str(yaml, &config).unwrap();
|
||||
assert!(!compiled.step_factories.is_empty());
|
||||
let (key, _factory) = &compiled.step_factories[0];
|
||||
assert!(key.contains("deno"), "factory key should contain 'deno', got: {key}");
|
||||
assert!(
|
||||
key.contains("deno"),
|
||||
"factory key should contain 'deno', got: {key}"
|
||||
);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -345,10 +342,7 @@ async fn deno_fetch_denied_host() {
|
||||
"expected permission error, got: {data:?}"
|
||||
);
|
||||
let err_msg = data["error"].as_str().unwrap();
|
||||
assert!(
|
||||
err_msg.contains("Permission denied"),
|
||||
"got: {err_msg}"
|
||||
);
|
||||
assert!(err_msg.contains("Permission denied"), "got: {err_msg}");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
@@ -384,8 +378,13 @@ async fn deno_fetch_returns_json() {
|
||||
async fn deno_fetch_post_with_body() {
|
||||
let server = wiremock::MockServer::start().await;
|
||||
wiremock::Mock::given(wiremock::matchers::method("POST"))
|
||||
.and(wiremock::matchers::header("content-type", "application/json"))
|
||||
.and(wiremock::matchers::body_json(serde_json::json!({"key": "val"})))
|
||||
.and(wiremock::matchers::header(
|
||||
"content-type",
|
||||
"application/json",
|
||||
))
|
||||
.and(wiremock::matchers::body_json(
|
||||
serde_json::json!({"key": "val"}),
|
||||
))
|
||||
.respond_with(wiremock::ResponseTemplate::new(201).set_body_string("created"))
|
||||
.mount(&server)
|
||||
.await;
|
||||
@@ -501,7 +500,11 @@ async fn deno_import_local_file() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let helper_path = dir.path().join("helper.js");
|
||||
let mut f = std::fs::File::create(&helper_path).unwrap();
|
||||
writeln!(f, "export function greet(name) {{ return `hello ${{name}}`; }}").unwrap();
|
||||
writeln!(
|
||||
f,
|
||||
"export function greet(name) {{ return `hello ${{name}}`; }}"
|
||||
)
|
||||
.unwrap();
|
||||
drop(f);
|
||||
|
||||
let main_path = dir.path().join("main.js");
|
||||
@@ -536,10 +539,7 @@ output("greeting", greet("world"));"#,
|
||||
async fn deno_dynamic_import_denied() {
|
||||
let server = wiremock::MockServer::start().await;
|
||||
wiremock::Mock::given(wiremock::matchers::any())
|
||||
.respond_with(
|
||||
wiremock::ResponseTemplate::new(200)
|
||||
.set_body_string("export const x = 1;"),
|
||||
)
|
||||
.respond_with(wiremock::ResponseTemplate::new(200).set_body_string("export const x = 1;"))
|
||||
.mount(&server)
|
||||
.await;
|
||||
|
||||
|
||||
@@ -105,7 +105,10 @@ workflow:
|
||||
"#;
|
||||
let instance = run_yaml_workflow(yaml).await;
|
||||
assert_eq!(instance.status, WorkflowStatus::Complete);
|
||||
assert_eq!(instance.data["message"], serde_json::json!("hello from deno"));
|
||||
assert_eq!(
|
||||
instance.data["message"],
|
||||
serde_json::json!("hello from deno")
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
@@ -114,8 +117,7 @@ async fn yaml_deno_with_fetch_wiremock() {
|
||||
wiremock::Mock::given(wiremock::matchers::method("GET"))
|
||||
.and(wiremock::matchers::path("/api/data"))
|
||||
.respond_with(
|
||||
wiremock::ResponseTemplate::new(200)
|
||||
.set_body_json(serde_json::json!({"value": 42})),
|
||||
wiremock::ResponseTemplate::new(200).set_body_json(serde_json::json!({"value": 42})),
|
||||
)
|
||||
.mount(&server)
|
||||
.await;
|
||||
@@ -325,8 +327,7 @@ workflow:
|
||||
const data = inputs();
|
||||
output("doubled", data.value * 2);
|
||||
"#;
|
||||
let instance =
|
||||
run_yaml_workflow_with_data(yaml, serde_json::json!({"value": 21})).await;
|
||||
let instance = run_yaml_workflow_with_data(yaml, serde_json::json!({"value": 21})).await;
|
||||
assert_eq!(instance.status, WorkflowStatus::Complete);
|
||||
assert_eq!(instance.data["doubled"], serde_json::json!(42));
|
||||
}
|
||||
@@ -547,10 +548,7 @@ workflow:
|
||||
match result {
|
||||
Err(e) => {
|
||||
let msg = e.to_string();
|
||||
assert!(
|
||||
msg.contains("config") || msg.contains("Deno"),
|
||||
"got: {msg}"
|
||||
);
|
||||
assert!(msg.contains("config") || msg.contains("Deno"), "got: {msg}");
|
||||
}
|
||||
Ok(_) => panic!("expected error for deno step without config"),
|
||||
}
|
||||
@@ -574,10 +572,7 @@ workflow:
|
||||
match result {
|
||||
Err(e) => {
|
||||
let msg = e.to_string();
|
||||
assert!(
|
||||
msg.contains("script") || msg.contains("file"),
|
||||
"got: {msg}"
|
||||
);
|
||||
assert!(msg.contains("script") || msg.contains("file"), "got: {msg}");
|
||||
}
|
||||
Ok(_) => panic!("expected error for deno step without script or file"),
|
||||
}
|
||||
@@ -633,8 +628,14 @@ workflow:
|
||||
"#;
|
||||
let config = HashMap::new();
|
||||
let compiled = load_single_workflow_from_str(yaml, &config).unwrap();
|
||||
let has_shell = compiled.step_factories.iter().any(|(k, _)| k.contains("shell"));
|
||||
let has_deno = compiled.step_factories.iter().any(|(k, _)| k.contains("deno"));
|
||||
let has_shell = compiled
|
||||
.step_factories
|
||||
.iter()
|
||||
.any(|(k, _)| k.contains("shell"));
|
||||
let has_deno = compiled
|
||||
.step_factories
|
||||
.iter()
|
||||
.any(|(k, _)| k.contains("deno"));
|
||||
assert!(has_shell, "should have shell factory");
|
||||
assert!(has_deno, "should have deno factory");
|
||||
}
|
||||
@@ -785,7 +786,10 @@ workflow:
|
||||
"#;
|
||||
let instance = run_yaml_workflow(yaml).await;
|
||||
assert_eq!(instance.status, WorkflowStatus::Complete);
|
||||
assert_eq!(instance.data["nested"]["a"]["b"]["c"], serde_json::json!(42));
|
||||
assert_eq!(
|
||||
instance.data["nested"]["a"]["b"]["c"],
|
||||
serde_json::json!(42)
|
||||
);
|
||||
assert_eq!(instance.data["array"], serde_json::json!([1, 2, 3]));
|
||||
assert!(instance.data["null_val"].is_null());
|
||||
assert_eq!(instance.data["bool_val"], serde_json::json!(false));
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::collections::HashMap;
|
||||
use std::io::Write;
|
||||
|
||||
use wfe_yaml::{load_workflow, load_single_workflow_from_str};
|
||||
use wfe_yaml::{load_single_workflow_from_str, load_workflow};
|
||||
|
||||
#[test]
|
||||
fn load_workflow_from_file() {
|
||||
@@ -35,7 +35,10 @@ fn load_workflow_from_nonexistent_file_returns_error() {
|
||||
let path = std::path::Path::new("/tmp/nonexistent_wfe_test_file_12345.yaml");
|
||||
let result = load_workflow(path, &HashMap::new());
|
||||
assert!(result.is_err());
|
||||
let err = match result { Err(e) => e.to_string(), Ok(_) => panic!("expected error") };
|
||||
let err = match result {
|
||||
Err(e) => e.to_string(),
|
||||
Ok(_) => panic!("expected error"),
|
||||
};
|
||||
assert!(
|
||||
err.contains("IO error") || err.contains("No such file"),
|
||||
"Expected IO error, got: {err}"
|
||||
@@ -47,7 +50,10 @@ fn load_workflow_from_str_with_invalid_yaml_returns_error() {
|
||||
let yaml = "this is not valid yaml: [[[";
|
||||
let result = load_single_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_err());
|
||||
let err = match result { Err(e) => e.to_string(), Ok(_) => panic!("expected error") };
|
||||
let err = match result {
|
||||
Err(e) => e.to_string(),
|
||||
Ok(_) => panic!("expected error"),
|
||||
};
|
||||
assert!(
|
||||
err.contains("YAML parse error"),
|
||||
"Expected YAML parse error, got: {err}"
|
||||
@@ -96,7 +102,10 @@ workflow:
|
||||
"#;
|
||||
let result = load_single_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_err());
|
||||
let err = match result { Err(e) => e.to_string(), Ok(_) => panic!("expected error") };
|
||||
let err = match result {
|
||||
Err(e) => e.to_string(),
|
||||
Ok(_) => panic!("expected error"),
|
||||
};
|
||||
assert!(
|
||||
err.contains("missing"),
|
||||
"Expected unresolved variable error, got: {err}"
|
||||
|
||||
@@ -55,9 +55,19 @@ async fn run_yaml_workflow_with_config(
|
||||
) -> wfe::models::WorkflowInstance {
|
||||
let compiled = load_single_workflow_from_str(yaml, config).unwrap();
|
||||
for step in &compiled.definition.steps {
|
||||
eprintln!(" step: {:?} type={} config={:?}", step.name, step.step_type, step.step_config);
|
||||
eprintln!(
|
||||
" step: {:?} type={} config={:?}",
|
||||
step.name, step.step_type, step.step_config
|
||||
);
|
||||
}
|
||||
eprintln!(" factories: {:?}", compiled.step_factories.iter().map(|(k, _)| k.clone()).collect::<Vec<_>>());
|
||||
eprintln!(
|
||||
" factories: {:?}",
|
||||
compiled
|
||||
.step_factories
|
||||
.iter()
|
||||
.map(|(k, _)| k.clone())
|
||||
.collect::<Vec<_>>()
|
||||
);
|
||||
|
||||
let persistence = Arc::new(InMemoryPersistenceProvider::new());
|
||||
let lock = Arc::new(InMemoryLockProvider::new());
|
||||
@@ -197,7 +207,9 @@ fn make_config(
|
||||
#[tokio::test]
|
||||
#[ignore = "requires containerd daemon"]
|
||||
async fn minimal_echo_in_containerd_via_workflow() {
|
||||
let _ = tracing_subscriber::fmt().with_env_filter("wfe_containerd=debug,wfe_core::executor=debug").try_init();
|
||||
let _ = tracing_subscriber::fmt()
|
||||
.with_env_filter("wfe_containerd=debug,wfe_core::executor=debug")
|
||||
.try_init();
|
||||
let Some(addr) = containerd_addr() else {
|
||||
eprintln!("SKIP: containerd not available");
|
||||
return;
|
||||
@@ -237,10 +249,7 @@ async fn minimal_echo_in_containerd_via_workflow() {
|
||||
eprintln!("Status: {:?}, Data: {:?}", instance.status, instance.data);
|
||||
assert_eq!(instance.status, WorkflowStatus::Complete);
|
||||
let data = instance.data.as_object().unwrap();
|
||||
assert_eq!(
|
||||
data.get("echo.status").and_then(|v| v.as_str()),
|
||||
Some("ok"),
|
||||
);
|
||||
assert_eq!(data.get("echo.status").and_then(|v| v.as_str()), Some("ok"),);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -259,79 +268,129 @@ async fn full_rust_pipeline_in_container() {
|
||||
let rustup_home = shared_tempdir("rustup");
|
||||
let workspace = shared_tempdir("workspace");
|
||||
|
||||
let config = make_config(
|
||||
&addr,
|
||||
&cargo_home,
|
||||
&rustup_home,
|
||||
Some(&workspace),
|
||||
);
|
||||
let config = make_config(&addr, &cargo_home, &rustup_home, Some(&workspace));
|
||||
|
||||
let steps = [
|
||||
containerd_step_yaml(
|
||||
"install-rust", "host", "if-not-present", "10m", None, false,
|
||||
"install-rust",
|
||||
"host",
|
||||
"if-not-present",
|
||||
"10m",
|
||||
None,
|
||||
false,
|
||||
" apt-get update && apt-get install -y curl gcc pkg-config libssl-dev\n\
|
||||
\x20 curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain stable",
|
||||
),
|
||||
containerd_step_yaml(
|
||||
"install-tools", "host", "never", "10m", None, false,
|
||||
"install-tools",
|
||||
"host",
|
||||
"never",
|
||||
"10m",
|
||||
None,
|
||||
false,
|
||||
" rustup component add clippy rustfmt llvm-tools-preview\n\
|
||||
\x20 cargo install cargo-audit cargo-deny cargo-nextest cargo-llvm-cov",
|
||||
),
|
||||
containerd_step_yaml(
|
||||
"create-project", "host", "never", "2m", None, true,
|
||||
"create-project",
|
||||
"host",
|
||||
"never",
|
||||
"2m",
|
||||
None,
|
||||
true,
|
||||
" cargo init /workspace/test-crate --name test-crate\n\
|
||||
\x20 cd /workspace/test-crate\n\
|
||||
\x20 echo '#[cfg(test)] mod tests { #[test] fn it_works() { assert_eq!(2+2,4); } }' >> src/main.rs",
|
||||
),
|
||||
containerd_step_yaml(
|
||||
"cargo-fmt", "none", "never", "2m",
|
||||
Some("/workspace/test-crate"), true,
|
||||
"cargo-fmt",
|
||||
"none",
|
||||
"never",
|
||||
"2m",
|
||||
Some("/workspace/test-crate"),
|
||||
true,
|
||||
" cargo fmt -- --check || cargo fmt",
|
||||
),
|
||||
containerd_step_yaml(
|
||||
"cargo-check", "none", "never", "5m",
|
||||
Some("/workspace/test-crate"), true,
|
||||
"cargo-check",
|
||||
"none",
|
||||
"never",
|
||||
"5m",
|
||||
Some("/workspace/test-crate"),
|
||||
true,
|
||||
" cargo check",
|
||||
),
|
||||
containerd_step_yaml(
|
||||
"cargo-clippy", "none", "never", "5m",
|
||||
Some("/workspace/test-crate"), true,
|
||||
"cargo-clippy",
|
||||
"none",
|
||||
"never",
|
||||
"5m",
|
||||
Some("/workspace/test-crate"),
|
||||
true,
|
||||
" cargo clippy -- -D warnings",
|
||||
),
|
||||
containerd_step_yaml(
|
||||
"cargo-test", "none", "never", "5m",
|
||||
Some("/workspace/test-crate"), true,
|
||||
"cargo-test",
|
||||
"none",
|
||||
"never",
|
||||
"5m",
|
||||
Some("/workspace/test-crate"),
|
||||
true,
|
||||
" cargo test",
|
||||
),
|
||||
containerd_step_yaml(
|
||||
"cargo-build", "none", "never", "5m",
|
||||
Some("/workspace/test-crate"), true,
|
||||
"cargo-build",
|
||||
"none",
|
||||
"never",
|
||||
"5m",
|
||||
Some("/workspace/test-crate"),
|
||||
true,
|
||||
" cargo build --release",
|
||||
),
|
||||
containerd_step_yaml(
|
||||
"cargo-nextest", "none", "never", "5m",
|
||||
Some("/workspace/test-crate"), true,
|
||||
"cargo-nextest",
|
||||
"none",
|
||||
"never",
|
||||
"5m",
|
||||
Some("/workspace/test-crate"),
|
||||
true,
|
||||
" cargo nextest run",
|
||||
),
|
||||
containerd_step_yaml(
|
||||
"cargo-llvm-cov", "none", "never", "5m",
|
||||
Some("/workspace/test-crate"), true,
|
||||
"cargo-llvm-cov",
|
||||
"none",
|
||||
"never",
|
||||
"5m",
|
||||
Some("/workspace/test-crate"),
|
||||
true,
|
||||
" cargo llvm-cov --summary-only",
|
||||
),
|
||||
containerd_step_yaml(
|
||||
"cargo-audit", "host", "never", "5m",
|
||||
Some("/workspace/test-crate"), true,
|
||||
"cargo-audit",
|
||||
"host",
|
||||
"never",
|
||||
"5m",
|
||||
Some("/workspace/test-crate"),
|
||||
true,
|
||||
" cargo audit || true",
|
||||
),
|
||||
containerd_step_yaml(
|
||||
"cargo-deny", "none", "never", "5m",
|
||||
Some("/workspace/test-crate"), true,
|
||||
"cargo-deny",
|
||||
"none",
|
||||
"never",
|
||||
"5m",
|
||||
Some("/workspace/test-crate"),
|
||||
true,
|
||||
" cargo deny init\n\
|
||||
\x20 cargo deny check || true",
|
||||
),
|
||||
containerd_step_yaml(
|
||||
"cargo-doc", "none", "never", "5m",
|
||||
Some("/workspace/test-crate"), true,
|
||||
"cargo-doc",
|
||||
"none",
|
||||
"never",
|
||||
"5m",
|
||||
Some("/workspace/test-crate"),
|
||||
true,
|
||||
" cargo doc --no-deps",
|
||||
),
|
||||
];
|
||||
|
||||
@@ -17,10 +17,7 @@ workflow:
|
||||
assert_eq!(parsed.workflow.version, 1);
|
||||
assert_eq!(parsed.workflow.steps.len(), 1);
|
||||
assert_eq!(parsed.workflow.steps[0].name, "hello");
|
||||
assert_eq!(
|
||||
parsed.workflow.steps[0].step_type.as_deref(),
|
||||
Some("shell")
|
||||
);
|
||||
assert_eq!(parsed.workflow.steps[0].step_type.as_deref(), Some("shell"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -263,20 +260,14 @@ workflow:
|
||||
let parsed: YamlWorkflow = serde_yaml::from_str(yaml).unwrap();
|
||||
assert_eq!(parsed.workflow.inputs.len(), 3);
|
||||
assert_eq!(parsed.workflow.inputs.get("repo_url").unwrap(), "string");
|
||||
assert_eq!(
|
||||
parsed.workflow.inputs.get("tags").unwrap(),
|
||||
"list<string>"
|
||||
);
|
||||
assert_eq!(parsed.workflow.inputs.get("tags").unwrap(), "list<string>");
|
||||
assert_eq!(parsed.workflow.inputs.get("verbose").unwrap(), "bool?");
|
||||
assert_eq!(parsed.workflow.outputs.len(), 2);
|
||||
assert_eq!(
|
||||
parsed.workflow.outputs.get("artifact_path").unwrap(),
|
||||
"string"
|
||||
);
|
||||
assert_eq!(
|
||||
parsed.workflow.outputs.get("exit_code").unwrap(),
|
||||
"integer"
|
||||
);
|
||||
assert_eq!(parsed.workflow.outputs.get("exit_code").unwrap(), "integer");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -60,7 +60,9 @@ struct CollectingLogSink {
|
||||
|
||||
impl CollectingLogSink {
|
||||
fn new() -> Self {
|
||||
Self { chunks: tokio::sync::Mutex::new(Vec::new()) }
|
||||
Self {
|
||||
chunks: tokio::sync::Mutex::new(Vec::new()),
|
||||
}
|
||||
}
|
||||
|
||||
async fn chunks(&self) -> Vec<wfe_core::traits::LogChunk> {
|
||||
@@ -242,11 +244,8 @@ workflow:
|
||||
run: echo "{wfe_prefix}[output result=$GREETING]"
|
||||
"#
|
||||
);
|
||||
let instance = run_yaml_workflow_with_data(
|
||||
&yaml,
|
||||
serde_json::json!({"greeting": "hi there"}),
|
||||
)
|
||||
.await;
|
||||
let instance =
|
||||
run_yaml_workflow_with_data(&yaml, serde_json::json!({"greeting": "hi there"})).await;
|
||||
assert_eq!(instance.status, WorkflowStatus::Complete);
|
||||
|
||||
if let Some(data) = instance.data.as_object() {
|
||||
@@ -320,19 +319,33 @@ workflow:
|
||||
assert_eq!(instance.status, WorkflowStatus::Complete);
|
||||
|
||||
let chunks = log_sink.chunks().await;
|
||||
assert!(chunks.len() >= 2, "expected at least 2 stdout chunks, got {}", chunks.len());
|
||||
assert!(
|
||||
chunks.len() >= 2,
|
||||
"expected at least 2 stdout chunks, got {}",
|
||||
chunks.len()
|
||||
);
|
||||
|
||||
let stdout_chunks: Vec<_> = chunks
|
||||
.iter()
|
||||
.filter(|c| c.stream == wfe_core::traits::LogStreamType::Stdout)
|
||||
.collect();
|
||||
assert!(stdout_chunks.len() >= 2, "expected at least 2 stdout chunks");
|
||||
assert!(
|
||||
stdout_chunks.len() >= 2,
|
||||
"expected at least 2 stdout chunks"
|
||||
);
|
||||
|
||||
let all_data: String = stdout_chunks.iter()
|
||||
let all_data: String = stdout_chunks
|
||||
.iter()
|
||||
.map(|c| String::from_utf8_lossy(&c.data).to_string())
|
||||
.collect();
|
||||
assert!(all_data.contains("line one"), "stdout should contain 'line one', got: {all_data}");
|
||||
assert!(all_data.contains("line two"), "stdout should contain 'line two', got: {all_data}");
|
||||
assert!(
|
||||
all_data.contains("line one"),
|
||||
"stdout should contain 'line one', got: {all_data}"
|
||||
);
|
||||
assert!(
|
||||
all_data.contains("line two"),
|
||||
"stdout should contain 'line two', got: {all_data}"
|
||||
);
|
||||
|
||||
// Verify chunk metadata.
|
||||
for chunk in &stdout_chunks {
|
||||
@@ -364,10 +377,14 @@ workflow:
|
||||
.collect();
|
||||
assert!(!stderr_chunks.is_empty(), "expected stderr chunks");
|
||||
|
||||
let stderr_data: String = stderr_chunks.iter()
|
||||
let stderr_data: String = stderr_chunks
|
||||
.iter()
|
||||
.map(|c| String::from_utf8_lossy(&c.data).to_string())
|
||||
.collect();
|
||||
assert!(stderr_data.contains("stderr output"), "stderr should contain 'stderr output', got: {stderr_data}");
|
||||
assert!(
|
||||
stderr_data.contains("stderr output"),
|
||||
"stderr should contain 'stderr output', got: {stderr_data}"
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
@@ -392,8 +409,14 @@ workflow:
|
||||
|
||||
let chunks = log_sink.chunks().await;
|
||||
let step_names: Vec<_> = chunks.iter().map(|c| c.step_name.as_str()).collect();
|
||||
assert!(step_names.contains(&"step-a"), "should have chunks from step-a");
|
||||
assert!(step_names.contains(&"step-b"), "should have chunks from step-b");
|
||||
assert!(
|
||||
step_names.contains(&"step-a"),
|
||||
"should have chunks from step-a"
|
||||
);
|
||||
assert!(
|
||||
step_names.contains(&"step-b"),
|
||||
"should have chunks from step-b"
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
@@ -412,7 +435,13 @@ workflow:
|
||||
let instance = run_yaml_workflow(yaml).await;
|
||||
assert_eq!(instance.status, WorkflowStatus::Complete);
|
||||
let data = instance.data.as_object().unwrap();
|
||||
assert!(data.get("echo-step.stdout").unwrap().as_str().unwrap().contains("no sink"));
|
||||
assert!(
|
||||
data.get("echo-step.stdout")
|
||||
.unwrap()
|
||||
.as_str()
|
||||
.unwrap()
|
||||
.contains("no sink")
|
||||
);
|
||||
}
|
||||
|
||||
// ── Security regression tests ────────────────────────────────────────
|
||||
@@ -431,11 +460,8 @@ workflow:
|
||||
run: echo "$PATH"
|
||||
"#;
|
||||
// Set a workflow data key "path" that would override PATH if not blocked.
|
||||
let instance = run_yaml_workflow_with_data(
|
||||
yaml,
|
||||
serde_json::json!({"path": "/attacker/bin"}),
|
||||
)
|
||||
.await;
|
||||
let instance =
|
||||
run_yaml_workflow_with_data(yaml, serde_json::json!({"path": "/attacker/bin"})).await;
|
||||
assert_eq!(instance.status, WorkflowStatus::Complete);
|
||||
|
||||
let data = instance.data.as_object().unwrap();
|
||||
@@ -463,11 +489,8 @@ workflow:
|
||||
run: echo "{wfe_prefix}[output val=$MY_CUSTOM_VAR]"
|
||||
"#
|
||||
);
|
||||
let instance = run_yaml_workflow_with_data(
|
||||
&yaml,
|
||||
serde_json::json!({"my_custom_var": "works"}),
|
||||
)
|
||||
.await;
|
||||
let instance =
|
||||
run_yaml_workflow_with_data(&yaml, serde_json::json!({"my_custom_var": "works"})).await;
|
||||
assert_eq!(instance.status, WorkflowStatus::Complete);
|
||||
|
||||
let data = instance.data.as_object().unwrap();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use wfe_yaml::types::{parse_type_string, SchemaType};
|
||||
use wfe_yaml::types::{SchemaType, parse_type_string};
|
||||
|
||||
#[test]
|
||||
fn parse_all_primitives() {
|
||||
|
||||
@@ -12,7 +12,10 @@ workflow:
|
||||
"#;
|
||||
let result = load_single_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_err());
|
||||
let err = match result { Err(e) => e.to_string(), Ok(_) => panic!("expected error") };
|
||||
let err = match result {
|
||||
Err(e) => e.to_string(),
|
||||
Ok(_) => panic!("expected error"),
|
||||
};
|
||||
assert!(
|
||||
err.contains("at least one step"),
|
||||
"Expected 'at least one step' error, got: {err}"
|
||||
@@ -30,7 +33,10 @@ workflow:
|
||||
"#;
|
||||
let result = load_single_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_err());
|
||||
let err = match result { Err(e) => e.to_string(), Ok(_) => panic!("expected error") };
|
||||
let err = match result {
|
||||
Err(e) => e.to_string(),
|
||||
Ok(_) => panic!("expected error"),
|
||||
};
|
||||
assert!(
|
||||
err.contains("type") && err.contains("parallel"),
|
||||
"Expected error about missing type or parallel, got: {err}"
|
||||
@@ -54,7 +60,10 @@ workflow:
|
||||
"#;
|
||||
let result = load_single_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_err());
|
||||
let err = match result { Err(e) => e.to_string(), Ok(_) => panic!("expected error") };
|
||||
let err = match result {
|
||||
Err(e) => e.to_string(),
|
||||
Ok(_) => panic!("expected error"),
|
||||
};
|
||||
assert!(
|
||||
err.contains("cannot have both"),
|
||||
"Expected 'cannot have both' error, got: {err}"
|
||||
@@ -79,7 +88,10 @@ workflow:
|
||||
"#;
|
||||
let result = load_single_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_err());
|
||||
let err = match result { Err(e) => e.to_string(), Ok(_) => panic!("expected error") };
|
||||
let err = match result {
|
||||
Err(e) => e.to_string(),
|
||||
Ok(_) => panic!("expected error"),
|
||||
};
|
||||
assert!(
|
||||
err.contains("Duplicate step name") && err.contains("deploy"),
|
||||
"Expected duplicate name error, got: {err}"
|
||||
@@ -100,7 +112,10 @@ workflow:
|
||||
"#;
|
||||
let result = load_single_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_err());
|
||||
let err = match result { Err(e) => e.to_string(), Ok(_) => panic!("expected error") };
|
||||
let err = match result {
|
||||
Err(e) => e.to_string(),
|
||||
Ok(_) => panic!("expected error"),
|
||||
};
|
||||
assert!(
|
||||
err.contains("config.run") || err.contains("config.file"),
|
||||
"Expected error about missing run/file, got: {err}"
|
||||
@@ -119,7 +134,10 @@ workflow:
|
||||
"#;
|
||||
let result = load_single_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_err());
|
||||
let err = match result { Err(e) => e.to_string(), Ok(_) => panic!("expected error") };
|
||||
let err = match result {
|
||||
Err(e) => e.to_string(),
|
||||
Ok(_) => panic!("expected error"),
|
||||
};
|
||||
assert!(
|
||||
err.contains("config"),
|
||||
"Expected error about missing config, got: {err}"
|
||||
@@ -142,7 +160,10 @@ workflow:
|
||||
"#;
|
||||
let result = load_single_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_err());
|
||||
let err = match result { Err(e) => e.to_string(), Ok(_) => panic!("expected error") };
|
||||
let err = match result {
|
||||
Err(e) => e.to_string(),
|
||||
Ok(_) => panic!("expected error"),
|
||||
};
|
||||
assert!(
|
||||
err.contains("panic"),
|
||||
"Expected error mentioning invalid type, got: {err}"
|
||||
@@ -165,7 +186,10 @@ workflow:
|
||||
"#;
|
||||
let result = load_single_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_err());
|
||||
let err = match result { Err(e) => e.to_string(), Ok(_) => panic!("expected error") };
|
||||
let err = match result {
|
||||
Err(e) => e.to_string(),
|
||||
Ok(_) => panic!("expected error"),
|
||||
};
|
||||
assert!(
|
||||
err.contains("crash"),
|
||||
"Expected error mentioning invalid type, got: {err}"
|
||||
@@ -185,7 +209,11 @@ workflow:
|
||||
run: echo hello
|
||||
"#;
|
||||
let result = load_single_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_ok(), "Valid workflow should pass, got: {:?}", result.err());
|
||||
assert!(
|
||||
result.is_ok(),
|
||||
"Valid workflow should pass, got: {:?}",
|
||||
result.err()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -203,7 +231,11 @@ workflow:
|
||||
run: echo a
|
||||
"#;
|
||||
let result = load_single_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_ok(), "Valid parallel workflow should pass, got: {:?}", result.err());
|
||||
assert!(
|
||||
result.is_ok(),
|
||||
"Valid parallel workflow should pass, got: {:?}",
|
||||
result.err()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -225,7 +257,10 @@ workflow:
|
||||
"#;
|
||||
let result = load_single_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_err());
|
||||
let err = match result { Err(e) => e.to_string(), Ok(_) => panic!("expected error") };
|
||||
let err = match result {
|
||||
Err(e) => e.to_string(),
|
||||
Ok(_) => panic!("expected error"),
|
||||
};
|
||||
assert!(
|
||||
err.contains("Duplicate step name"),
|
||||
"Expected duplicate name error for hook, got: {err}"
|
||||
@@ -250,7 +285,11 @@ workflow:
|
||||
run: echo ok
|
||||
"#;
|
||||
let result = load_single_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_ok(), "Valid on_success hook should pass, got: {:?}", result.err());
|
||||
assert!(
|
||||
result.is_ok(),
|
||||
"Valid on_success hook should pass, got: {:?}",
|
||||
result.err()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -271,7 +310,11 @@ workflow:
|
||||
run: cleanup.sh
|
||||
"#;
|
||||
let result = load_single_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_ok(), "Valid ensure hook should pass, got: {:?}", result.err());
|
||||
assert!(
|
||||
result.is_ok(),
|
||||
"Valid ensure hook should pass, got: {:?}",
|
||||
result.err()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -320,7 +363,10 @@ workflow:
|
||||
"#;
|
||||
let result = load_single_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_err());
|
||||
let err = match result { Err(e) => e.to_string(), Ok(_) => panic!("expected error") };
|
||||
let err = match result {
|
||||
Err(e) => e.to_string(),
|
||||
Ok(_) => panic!("expected error"),
|
||||
};
|
||||
assert!(
|
||||
err.contains("Duplicate step name") && err.contains("task-a"),
|
||||
"Expected duplicate name in parallel children, got: {err}"
|
||||
@@ -341,7 +387,10 @@ workflow:
|
||||
"#;
|
||||
let result = load_single_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_err());
|
||||
let err = match result { Err(e) => e.to_string(), Ok(_) => panic!("expected error") };
|
||||
let err = match result {
|
||||
Err(e) => e.to_string(),
|
||||
Ok(_) => panic!("expected error"),
|
||||
};
|
||||
assert!(
|
||||
err.contains("config"),
|
||||
"Expected error about missing config, got: {err}"
|
||||
@@ -362,7 +411,10 @@ workflow:
|
||||
"#;
|
||||
let result = load_single_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_err());
|
||||
let err = match result { Err(e) => e.to_string(), Ok(_) => panic!("expected error") };
|
||||
let err = match result {
|
||||
Err(e) => e.to_string(),
|
||||
Ok(_) => panic!("expected error"),
|
||||
};
|
||||
assert!(
|
||||
err.contains("config.workflow"),
|
||||
"Expected error about missing config.workflow, got: {err}"
|
||||
@@ -382,7 +434,11 @@ workflow:
|
||||
workflow: child-wf
|
||||
"#;
|
||||
let result = load_single_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_ok(), "Valid workflow step should pass, got: {:?}", result.err());
|
||||
assert!(
|
||||
result.is_ok(),
|
||||
"Valid workflow step should pass, got: {:?}",
|
||||
result.err()
|
||||
);
|
||||
}
|
||||
|
||||
// --- Multi-workflow validation tests ---
|
||||
@@ -407,7 +463,11 @@ workflows:
|
||||
run: cargo test
|
||||
"#;
|
||||
let result = load_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_ok(), "Valid multi-workflow should pass, got: {:?}", result.err());
|
||||
assert!(
|
||||
result.is_ok(),
|
||||
"Valid multi-workflow should pass, got: {:?}",
|
||||
result.err()
|
||||
);
|
||||
assert_eq!(result.unwrap().len(), 2);
|
||||
}
|
||||
|
||||
@@ -432,7 +492,10 @@ workflows:
|
||||
"#;
|
||||
let result = load_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_err());
|
||||
let err = match result { Err(e) => e.to_string(), Ok(_) => panic!("expected error") };
|
||||
let err = match result {
|
||||
Err(e) => e.to_string(),
|
||||
Ok(_) => panic!("expected error"),
|
||||
};
|
||||
assert!(
|
||||
err.contains("Duplicate workflow ID"),
|
||||
"Expected duplicate workflow ID error, got: {err}"
|
||||
@@ -461,7 +524,10 @@ workflows:
|
||||
"#;
|
||||
let result = load_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_err());
|
||||
let err = match result { Err(e) => e.to_string(), Ok(_) => panic!("expected error") };
|
||||
let err = match result {
|
||||
Err(e) => e.to_string(),
|
||||
Ok(_) => panic!("expected error"),
|
||||
};
|
||||
assert!(
|
||||
err.contains("Cannot specify both"),
|
||||
"Expected error about both workflow and workflows, got: {err}"
|
||||
@@ -476,7 +542,10 @@ something_else:
|
||||
"#;
|
||||
let result = load_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_err());
|
||||
let err = match result { Err(e) => e.to_string(), Ok(_) => panic!("expected error") };
|
||||
let err = match result {
|
||||
Err(e) => e.to_string(),
|
||||
Ok(_) => panic!("expected error"),
|
||||
};
|
||||
assert!(
|
||||
err.contains("Must specify either"),
|
||||
"Expected error about missing workflow/workflows, got: {err}"
|
||||
@@ -490,7 +559,10 @@ workflows: []
|
||||
"#;
|
||||
let result = load_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_err());
|
||||
let err = match result { Err(e) => e.to_string(), Ok(_) => panic!("expected error") };
|
||||
let err = match result {
|
||||
Err(e) => e.to_string(),
|
||||
Ok(_) => panic!("expected error"),
|
||||
};
|
||||
assert!(
|
||||
err.contains("empty"),
|
||||
"Expected error about empty workflows, got: {err}"
|
||||
@@ -520,7 +592,10 @@ workflows:
|
||||
"#;
|
||||
let result = load_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_err());
|
||||
let err = match result { Err(e) => e.to_string(), Ok(_) => panic!("expected error") };
|
||||
let err = match result {
|
||||
Err(e) => e.to_string(),
|
||||
Ok(_) => panic!("expected error"),
|
||||
};
|
||||
assert!(
|
||||
err.contains("Circular workflow reference"),
|
||||
"Expected circular reference error, got: {err}"
|
||||
@@ -541,7 +616,10 @@ workflows:
|
||||
"#;
|
||||
let result = load_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_err());
|
||||
let err = match result { Err(e) => e.to_string(), Ok(_) => panic!("expected error") };
|
||||
let err = match result {
|
||||
Err(e) => e.to_string(),
|
||||
Ok(_) => panic!("expected error"),
|
||||
};
|
||||
assert!(
|
||||
err.contains("Circular workflow reference"),
|
||||
"Expected circular reference error, got: {err}"
|
||||
@@ -568,7 +646,11 @@ workflows:
|
||||
run: echo working
|
||||
"#;
|
||||
let result = load_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_ok(), "Valid workflow reference should pass, got: {:?}", result.err());
|
||||
assert!(
|
||||
result.is_ok(),
|
||||
"Valid workflow reference should pass, got: {:?}",
|
||||
result.err()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -585,7 +667,11 @@ workflow:
|
||||
workflow: some-external-wf
|
||||
"#;
|
||||
let result = load_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_ok(), "External workflow ref should not error, got: {:?}", result.err());
|
||||
assert!(
|
||||
result.is_ok(),
|
||||
"External workflow ref should not error, got: {:?}",
|
||||
result.err()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -609,7 +695,10 @@ workflows:
|
||||
"#;
|
||||
let result = load_single_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_err());
|
||||
let err = match result { Err(e) => e.to_string(), Ok(_) => panic!("expected error") };
|
||||
let err = match result {
|
||||
Err(e) => e.to_string(),
|
||||
Ok(_) => panic!("expected error"),
|
||||
};
|
||||
assert!(
|
||||
err.contains("Expected single workflow"),
|
||||
"Expected single workflow error, got: {err}"
|
||||
@@ -631,7 +720,11 @@ workflows:
|
||||
run: echo hello
|
||||
"#;
|
||||
let result = load_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_ok(), "Single workflow in multi-mode should pass, got: {:?}", result.err());
|
||||
assert!(
|
||||
result.is_ok(),
|
||||
"Single workflow in multi-mode should pass, got: {:?}",
|
||||
result.err()
|
||||
);
|
||||
assert_eq!(result.unwrap().len(), 1);
|
||||
}
|
||||
|
||||
@@ -662,7 +755,11 @@ workflows:
|
||||
run: echo gamma
|
||||
"#;
|
||||
let result = load_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_ok(), "Multiple independent workflows should pass, got: {:?}", result.err());
|
||||
assert!(
|
||||
result.is_ok(),
|
||||
"Multiple independent workflows should pass, got: {:?}",
|
||||
result.err()
|
||||
);
|
||||
assert_eq!(result.unwrap().len(), 3);
|
||||
}
|
||||
|
||||
@@ -686,7 +783,11 @@ workflows:
|
||||
run: echo working
|
||||
"#;
|
||||
let result = load_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_ok(), "Cross-referenced workflows should pass, got: {:?}", result.err());
|
||||
assert!(
|
||||
result.is_ok(),
|
||||
"Cross-referenced workflows should pass, got: {:?}",
|
||||
result.err()
|
||||
);
|
||||
}
|
||||
|
||||
// --- Cycle detection edge cases ---
|
||||
@@ -719,7 +820,10 @@ workflows:
|
||||
"#;
|
||||
let result = load_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_err());
|
||||
let err = match result { Err(e) => e.to_string(), Ok(_) => panic!("expected error") };
|
||||
let err = match result {
|
||||
Err(e) => e.to_string(),
|
||||
Ok(_) => panic!("expected error"),
|
||||
};
|
||||
assert!(
|
||||
err.contains("Circular workflow reference"),
|
||||
"Expected circular reference error for 3-node cycle, got: {err}"
|
||||
@@ -753,7 +857,11 @@ workflows:
|
||||
run: echo done
|
||||
"#;
|
||||
let result = load_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_ok(), "Linear chain should not be a cycle, got: {:?}", result.err());
|
||||
assert!(
|
||||
result.is_ok(),
|
||||
"Linear chain should not be a cycle, got: {:?}",
|
||||
result.err()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -794,7 +902,11 @@ workflows:
|
||||
run: echo done
|
||||
"#;
|
||||
let result = load_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_ok(), "Diamond dependency should not be a cycle, got: {:?}", result.err());
|
||||
assert!(
|
||||
result.is_ok(),
|
||||
"Diamond dependency should not be a cycle, got: {:?}",
|
||||
result.err()
|
||||
);
|
||||
}
|
||||
|
||||
// --- Deno step validation ---
|
||||
@@ -811,7 +923,10 @@ workflow:
|
||||
"#;
|
||||
let result = load_single_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_err());
|
||||
let err = match result { Err(e) => e.to_string(), Ok(_) => panic!("expected error") };
|
||||
let err = match result {
|
||||
Err(e) => e.to_string(),
|
||||
Ok(_) => panic!("expected error"),
|
||||
};
|
||||
assert!(
|
||||
err.contains("Deno") && err.contains("config"),
|
||||
"Expected Deno config error, got: {err}"
|
||||
@@ -833,7 +948,10 @@ workflow:
|
||||
"#;
|
||||
let result = load_single_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_err());
|
||||
let err = match result { Err(e) => e.to_string(), Ok(_) => panic!("expected error") };
|
||||
let err = match result {
|
||||
Err(e) => e.to_string(),
|
||||
Ok(_) => panic!("expected error"),
|
||||
};
|
||||
assert!(
|
||||
err.contains("Deno") && (err.contains("script") || err.contains("file")),
|
||||
"Expected Deno script/file error, got: {err}"
|
||||
@@ -854,7 +972,10 @@ workflow:
|
||||
"#;
|
||||
let result = load_single_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_err());
|
||||
let err = match result { Err(e) => e.to_string(), Ok(_) => panic!("expected error") };
|
||||
let err = match result {
|
||||
Err(e) => e.to_string(),
|
||||
Ok(_) => panic!("expected error"),
|
||||
};
|
||||
assert!(
|
||||
err.contains("BuildKit") && err.contains("config"),
|
||||
"Expected BuildKit config error, got: {err}"
|
||||
@@ -875,7 +996,10 @@ workflow:
|
||||
"#;
|
||||
let result = load_single_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_err());
|
||||
let err = match result { Err(e) => e.to_string(), Ok(_) => panic!("expected error") };
|
||||
let err = match result {
|
||||
Err(e) => e.to_string(),
|
||||
Ok(_) => panic!("expected error"),
|
||||
};
|
||||
assert!(
|
||||
err.contains("dockerfile"),
|
||||
"Expected dockerfile error, got: {err}"
|
||||
@@ -896,7 +1020,10 @@ workflow:
|
||||
"#;
|
||||
let result = load_single_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_err());
|
||||
let err = match result { Err(e) => e.to_string(), Ok(_) => panic!("expected error") };
|
||||
let err = match result {
|
||||
Err(e) => e.to_string(),
|
||||
Ok(_) => panic!("expected error"),
|
||||
};
|
||||
assert!(
|
||||
err.contains("context"),
|
||||
"Expected context error, got: {err}"
|
||||
@@ -919,7 +1046,10 @@ workflow:
|
||||
"#;
|
||||
let result = load_single_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_err());
|
||||
let err = match result { Err(e) => e.to_string(), Ok(_) => panic!("expected error") };
|
||||
let err = match result {
|
||||
Err(e) => e.to_string(),
|
||||
Ok(_) => panic!("expected error"),
|
||||
};
|
||||
assert!(
|
||||
err.contains("push") && err.contains("tags"),
|
||||
"Expected push/tags error, got: {err}"
|
||||
@@ -970,7 +1100,10 @@ workflow:
|
||||
"#;
|
||||
let result = load_single_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_err());
|
||||
let err = match result { Err(e) => e.to_string(), Ok(_) => panic!("expected error") };
|
||||
let err = match result {
|
||||
Err(e) => e.to_string(),
|
||||
Ok(_) => panic!("expected error"),
|
||||
};
|
||||
assert!(
|
||||
err.contains("Containerd") && err.contains("config"),
|
||||
"Expected Containerd config error, got: {err}"
|
||||
@@ -991,11 +1124,11 @@ workflow:
|
||||
"#;
|
||||
let result = load_single_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_err());
|
||||
let err = match result { Err(e) => e.to_string(), Ok(_) => panic!("expected error") };
|
||||
assert!(
|
||||
err.contains("image"),
|
||||
"Expected image error, got: {err}"
|
||||
);
|
||||
let err = match result {
|
||||
Err(e) => e.to_string(),
|
||||
Ok(_) => panic!("expected error"),
|
||||
};
|
||||
assert!(err.contains("image"), "Expected image error, got: {err}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1012,7 +1145,10 @@ workflow:
|
||||
"#;
|
||||
let result = load_single_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_err());
|
||||
let err = match result { Err(e) => e.to_string(), Ok(_) => panic!("expected error") };
|
||||
let err = match result {
|
||||
Err(e) => e.to_string(),
|
||||
Ok(_) => panic!("expected error"),
|
||||
};
|
||||
assert!(
|
||||
err.contains("run") || err.contains("command"),
|
||||
"Expected run/command error, got: {err}"
|
||||
@@ -1037,7 +1173,10 @@ workflow:
|
||||
"#;
|
||||
let result = load_single_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_err());
|
||||
let err = match result { Err(e) => e.to_string(), Ok(_) => panic!("expected error") };
|
||||
let err = match result {
|
||||
Err(e) => e.to_string(),
|
||||
Ok(_) => panic!("expected error"),
|
||||
};
|
||||
assert!(
|
||||
err.contains("cannot have both"),
|
||||
"Expected 'cannot have both' error, got: {err}"
|
||||
@@ -1060,7 +1199,10 @@ workflow:
|
||||
"#;
|
||||
let result = load_single_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_err());
|
||||
let err = match result { Err(e) => e.to_string(), Ok(_) => panic!("expected error") };
|
||||
let err = match result {
|
||||
Err(e) => e.to_string(),
|
||||
Ok(_) => panic!("expected error"),
|
||||
};
|
||||
assert!(
|
||||
err.contains("network") && err.contains("overlay"),
|
||||
"Expected invalid network error, got: {err}"
|
||||
@@ -1111,7 +1253,10 @@ workflow:
|
||||
"#;
|
||||
let result = load_single_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_err());
|
||||
let err = match result { Err(e) => e.to_string(), Ok(_) => panic!("expected error") };
|
||||
let err = match result {
|
||||
Err(e) => e.to_string(),
|
||||
Ok(_) => panic!("expected error"),
|
||||
};
|
||||
assert!(
|
||||
err.contains("pull") && err.contains("aggressive"),
|
||||
"Expected invalid pull policy error, got: {err}"
|
||||
@@ -1190,7 +1335,10 @@ workflow:
|
||||
"#;
|
||||
let result = load_single_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_err());
|
||||
let err = match result { Err(e) => e.to_string(), Ok(_) => panic!("expected error") };
|
||||
let err = match result {
|
||||
Err(e) => e.to_string(),
|
||||
Ok(_) => panic!("expected error"),
|
||||
};
|
||||
assert!(
|
||||
err.contains("config"),
|
||||
"Expected config error for invalid hook, got: {err}"
|
||||
@@ -1214,7 +1362,10 @@ workflow:
|
||||
"#;
|
||||
let result = load_single_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_err());
|
||||
let err = match result { Err(e) => e.to_string(), Ok(_) => panic!("expected error") };
|
||||
let err = match result {
|
||||
Err(e) => e.to_string(),
|
||||
Ok(_) => panic!("expected error"),
|
||||
};
|
||||
assert!(
|
||||
err.contains("config"),
|
||||
"Expected config error for invalid on_success hook, got: {err}"
|
||||
@@ -1238,7 +1389,10 @@ workflow:
|
||||
"#;
|
||||
let result = load_single_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_err());
|
||||
let err = match result { Err(e) => e.to_string(), Ok(_) => panic!("expected error") };
|
||||
let err = match result {
|
||||
Err(e) => e.to_string(),
|
||||
Ok(_) => panic!("expected error"),
|
||||
};
|
||||
assert!(
|
||||
err.contains("config"),
|
||||
"Expected config error for invalid ensure hook, got: {err}"
|
||||
@@ -1261,7 +1415,10 @@ workflow:
|
||||
"#;
|
||||
let result = load_single_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_err());
|
||||
let err = match result { Err(e) => e.to_string(), Ok(_) => panic!("expected error") };
|
||||
let err = match result {
|
||||
Err(e) => e.to_string(),
|
||||
Ok(_) => panic!("expected error"),
|
||||
};
|
||||
assert!(
|
||||
err.contains("config"),
|
||||
"Expected config error for deeply nested invalid step, got: {err}"
|
||||
@@ -1301,7 +1458,10 @@ workflows:
|
||||
"#;
|
||||
let result = load_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_err());
|
||||
let err = match result { Err(e) => e.to_string(), Ok(_) => panic!("expected error") };
|
||||
let err = match result {
|
||||
Err(e) => e.to_string(),
|
||||
Ok(_) => panic!("expected error"),
|
||||
};
|
||||
assert!(
|
||||
err.contains("Circular workflow reference"),
|
||||
"Expected circular reference from hooks, got: {err}"
|
||||
@@ -1339,7 +1499,10 @@ workflows:
|
||||
"#;
|
||||
let result = load_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_err());
|
||||
let err = match result { Err(e) => e.to_string(), Ok(_) => panic!("expected error") };
|
||||
let err = match result {
|
||||
Err(e) => e.to_string(),
|
||||
Ok(_) => panic!("expected error"),
|
||||
};
|
||||
assert!(
|
||||
err.contains("Circular workflow reference"),
|
||||
"Expected circular reference from ensure hooks, got: {err}"
|
||||
@@ -1371,7 +1534,10 @@ workflows:
|
||||
"#;
|
||||
let result = load_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_err());
|
||||
let err = match result { Err(e) => e.to_string(), Ok(_) => panic!("expected error") };
|
||||
let err = match result {
|
||||
Err(e) => e.to_string(),
|
||||
Ok(_) => panic!("expected error"),
|
||||
};
|
||||
assert!(
|
||||
err.contains("Circular workflow reference"),
|
||||
"Expected circular reference from parallel blocks, got: {err}"
|
||||
@@ -1394,7 +1560,10 @@ workflow:
|
||||
"#;
|
||||
let result = load_single_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_err());
|
||||
let err = match result { Err(e) => e.to_string(), Ok(_) => panic!("expected error") };
|
||||
let err = match result {
|
||||
Err(e) => e.to_string(),
|
||||
Ok(_) => panic!("expected error"),
|
||||
};
|
||||
assert!(
|
||||
err.contains("Unknown step type") && err.contains("terraform"),
|
||||
"Expected unknown step type error, got: {err}"
|
||||
@@ -1408,7 +1577,10 @@ fn load_workflow_from_nonexistent_file_returns_io_error() {
|
||||
let path = std::path::Path::new("/tmp/nonexistent_wfe_test_file.yaml");
|
||||
let result = wfe_yaml::load_workflow(path, &HashMap::new());
|
||||
assert!(result.is_err());
|
||||
let err = match result { Err(e) => e.to_string(), Ok(_) => panic!("expected error") };
|
||||
let err = match result {
|
||||
Err(e) => e.to_string(),
|
||||
Ok(_) => panic!("expected error"),
|
||||
};
|
||||
assert!(
|
||||
err.contains("IO error") || err.contains("No such file"),
|
||||
"Expected IO error, got: {err}"
|
||||
@@ -1435,7 +1607,11 @@ workflow:
|
||||
equals: true
|
||||
"#;
|
||||
let result = load_single_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_ok(), "Field path to known input should pass, got: {:?}", result.err());
|
||||
assert!(
|
||||
result.is_ok(),
|
||||
"Field path to known input should pass, got: {:?}",
|
||||
result.err()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1458,7 +1634,11 @@ workflow:
|
||||
equals: success
|
||||
"#;
|
||||
let result = load_single_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_ok(), "Field path to known output should pass, got: {:?}", result.err());
|
||||
assert!(
|
||||
result.is_ok(),
|
||||
"Field path to known output should pass, got: {:?}",
|
||||
result.err()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1480,7 +1660,10 @@ workflow:
|
||||
"#;
|
||||
let result = load_single_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_err());
|
||||
let err = match result { Err(e) => e.to_string(), Ok(_) => panic!("expected error") };
|
||||
let err = match result {
|
||||
Err(e) => e.to_string(),
|
||||
Ok(_) => panic!("expected error"),
|
||||
};
|
||||
assert!(
|
||||
err.contains("unknown input field") && err.contains("nonexistent"),
|
||||
"Expected unknown input field error, got: {err}"
|
||||
@@ -1508,7 +1691,10 @@ workflow:
|
||||
"#;
|
||||
let result = load_single_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_err());
|
||||
let err = match result { Err(e) => e.to_string(), Ok(_) => panic!("expected error") };
|
||||
let err = match result {
|
||||
Err(e) => e.to_string(),
|
||||
Ok(_) => panic!("expected error"),
|
||||
};
|
||||
assert!(
|
||||
err.contains("unknown output field") && err.contains("missing"),
|
||||
"Expected unknown output field error, got: {err}"
|
||||
@@ -1534,7 +1720,10 @@ workflow:
|
||||
"#;
|
||||
let result = load_single_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_err());
|
||||
let err = match result { Err(e) => e.to_string(), Ok(_) => panic!("expected error") };
|
||||
let err = match result {
|
||||
Err(e) => e.to_string(),
|
||||
Ok(_) => panic!("expected error"),
|
||||
};
|
||||
assert!(
|
||||
err.contains("gt/gte/lt/lte") && err.contains("number/integer"),
|
||||
"Expected type mismatch error, got: {err}"
|
||||
@@ -1559,7 +1748,11 @@ workflow:
|
||||
gt: 5
|
||||
"#;
|
||||
let result = load_single_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_ok(), "gt on number should pass, got: {:?}", result.err());
|
||||
assert!(
|
||||
result.is_ok(),
|
||||
"gt on number should pass, got: {:?}",
|
||||
result.err()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1581,7 +1774,10 @@ workflow:
|
||||
"#;
|
||||
let result = load_single_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_err());
|
||||
let err = match result { Err(e) => e.to_string(), Ok(_) => panic!("expected error") };
|
||||
let err = match result {
|
||||
Err(e) => e.to_string(),
|
||||
Ok(_) => panic!("expected error"),
|
||||
};
|
||||
assert!(
|
||||
err.contains("contains") && err.contains("string/list"),
|
||||
"Expected type mismatch error for contains, got: {err}"
|
||||
@@ -1606,7 +1802,11 @@ workflow:
|
||||
contains: needle
|
||||
"#;
|
||||
let result = load_single_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_ok(), "contains on string should pass, got: {:?}", result.err());
|
||||
assert!(
|
||||
result.is_ok(),
|
||||
"contains on string should pass, got: {:?}",
|
||||
result.err()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1627,7 +1827,11 @@ workflow:
|
||||
contains: release
|
||||
"#;
|
||||
let result = load_single_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_ok(), "contains on list should pass, got: {:?}", result.err());
|
||||
assert!(
|
||||
result.is_ok(),
|
||||
"contains on list should pass, got: {:?}",
|
||||
result.err()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1649,7 +1853,10 @@ workflow:
|
||||
"#;
|
||||
let result = load_single_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_err());
|
||||
let err = match result { Err(e) => e.to_string(), Ok(_) => panic!("expected error") };
|
||||
let err = match result {
|
||||
Err(e) => e.to_string(),
|
||||
Ok(_) => panic!("expected error"),
|
||||
};
|
||||
assert!(
|
||||
err.contains("is_null/is_not_null") && err.contains("optional"),
|
||||
"Expected type mismatch error for is_null, got: {err}"
|
||||
@@ -1674,7 +1881,11 @@ workflow:
|
||||
is_null: true
|
||||
"#;
|
||||
let result = load_single_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_ok(), "is_null on optional should pass, got: {:?}", result.err());
|
||||
assert!(
|
||||
result.is_ok(),
|
||||
"is_null on optional should pass, got: {:?}",
|
||||
result.err()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1693,7 +1904,10 @@ workflow:
|
||||
"#;
|
||||
let result = load_single_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_err());
|
||||
let err = match result { Err(e) => e.to_string(), Ok(_) => panic!("expected error") };
|
||||
let err = match result {
|
||||
Err(e) => e.to_string(),
|
||||
Ok(_) => panic!("expected error"),
|
||||
};
|
||||
assert!(
|
||||
err.contains("never produced") && err.contains("result"),
|
||||
"Expected unused output error, got: {err}"
|
||||
@@ -1717,7 +1931,11 @@ workflow:
|
||||
- name: result
|
||||
"#;
|
||||
let result = load_single_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_ok(), "Output produced by step should pass, got: {:?}", result.err());
|
||||
assert!(
|
||||
result.is_ok(),
|
||||
"Output produced by step should pass, got: {:?}",
|
||||
result.err()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1734,7 +1952,11 @@ workflow:
|
||||
run: echo hi
|
||||
"#;
|
||||
let result = load_single_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_ok(), "No outputs schema should not cause error, got: {:?}", result.err());
|
||||
assert!(
|
||||
result.is_ok(),
|
||||
"No outputs schema should not cause error, got: {:?}",
|
||||
result.err()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1780,7 +2002,10 @@ workflow:
|
||||
"#;
|
||||
let result = load_single_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_err());
|
||||
let err = match result { Err(e) => e.to_string(), Ok(_) => panic!("expected error") };
|
||||
let err = match result {
|
||||
Err(e) => e.to_string(),
|
||||
Ok(_) => panic!("expected error"),
|
||||
};
|
||||
assert!(
|
||||
err.contains("inputs") && err.contains("outputs"),
|
||||
"Expected error about invalid path segment, got: {err}"
|
||||
@@ -1826,9 +2051,12 @@ workflow:
|
||||
let main_path = dir.path().join("main.yaml");
|
||||
std::fs::write(&main_path, &main_yaml).unwrap();
|
||||
|
||||
let result =
|
||||
wfe_yaml::load_workflow_with_includes(&main_yaml, &main_path, &HashMap::new());
|
||||
assert!(result.is_ok(), "Include single file should work, got: {:?}", result.err());
|
||||
let result = wfe_yaml::load_workflow_with_includes(&main_yaml, &main_path, &HashMap::new());
|
||||
assert!(
|
||||
result.is_ok(),
|
||||
"Include single file should work, got: {:?}",
|
||||
result.err()
|
||||
);
|
||||
let workflows = result.unwrap();
|
||||
assert_eq!(workflows.len(), 2);
|
||||
let ids: Vec<&str> = workflows.iter().map(|w| w.definition.id.as_str()).collect();
|
||||
@@ -1887,9 +2115,12 @@ workflow:
|
||||
let main_path = dir.path().join("main.yaml");
|
||||
std::fs::write(&main_path, main_yaml).unwrap();
|
||||
|
||||
let result =
|
||||
wfe_yaml::load_workflow_with_includes(main_yaml, &main_path, &HashMap::new());
|
||||
assert!(result.is_ok(), "Include multiple files should work, got: {:?}", result.err());
|
||||
let result = wfe_yaml::load_workflow_with_includes(main_yaml, &main_path, &HashMap::new());
|
||||
assert!(
|
||||
result.is_ok(),
|
||||
"Include multiple files should work, got: {:?}",
|
||||
result.err()
|
||||
);
|
||||
let workflows = result.unwrap();
|
||||
assert_eq!(workflows.len(), 3);
|
||||
}
|
||||
@@ -1931,9 +2162,12 @@ workflow:
|
||||
let main_path = dir.path().join("main.yaml");
|
||||
std::fs::write(&main_path, main_yaml).unwrap();
|
||||
|
||||
let result =
|
||||
wfe_yaml::load_workflow_with_includes(main_yaml, &main_path, &HashMap::new());
|
||||
assert!(result.is_ok(), "Override should work, got: {:?}", result.err());
|
||||
let result = wfe_yaml::load_workflow_with_includes(main_yaml, &main_path, &HashMap::new());
|
||||
assert!(
|
||||
result.is_ok(),
|
||||
"Override should work, got: {:?}",
|
||||
result.err()
|
||||
);
|
||||
let workflows = result.unwrap();
|
||||
// Only 1 workflow since main takes precedence over included
|
||||
assert_eq!(workflows.len(), 1);
|
||||
@@ -1972,10 +2206,12 @@ workflow:
|
||||
let main_path = dir.path().join("main.yaml");
|
||||
std::fs::write(&main_path, main_yaml).unwrap();
|
||||
|
||||
let result =
|
||||
wfe_yaml::load_workflow_with_includes(main_yaml, &main_path, &HashMap::new());
|
||||
let result = wfe_yaml::load_workflow_with_includes(main_yaml, &main_path, &HashMap::new());
|
||||
assert!(result.is_err());
|
||||
let err = match result { Err(e) => e.to_string(), Ok(_) => panic!("expected error") };
|
||||
let err = match result {
|
||||
Err(e) => e.to_string(),
|
||||
Ok(_) => panic!("expected error"),
|
||||
};
|
||||
assert!(
|
||||
err.contains("nonexistent") || err.contains("not found") || err.contains("No such file"),
|
||||
"Expected file not found error, got: {err}"
|
||||
@@ -2018,10 +2254,12 @@ workflow:
|
||||
|
||||
let a_path = dir.path().join("a.yaml");
|
||||
|
||||
let result =
|
||||
wfe_yaml::load_workflow_with_includes(a_yaml, &a_path, &HashMap::new());
|
||||
let result = wfe_yaml::load_workflow_with_includes(a_yaml, &a_path, &HashMap::new());
|
||||
assert!(result.is_err());
|
||||
let err = match result { Err(e) => e.to_string(), Ok(_) => panic!("expected error") };
|
||||
let err = match result {
|
||||
Err(e) => e.to_string(),
|
||||
Ok(_) => panic!("expected error"),
|
||||
};
|
||||
assert!(
|
||||
err.contains("Circular include"),
|
||||
"Expected circular include error, got: {err}"
|
||||
@@ -2053,7 +2291,11 @@ workflow:
|
||||
equals: true
|
||||
"#;
|
||||
let result = load_single_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_ok(), "equals should work on all types, got: {:?}", result.err());
|
||||
assert!(
|
||||
result.is_ok(),
|
||||
"equals should work on all types, got: {:?}",
|
||||
result.err()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -2074,7 +2316,11 @@ workflow:
|
||||
gte: 10
|
||||
"#;
|
||||
let result = load_single_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_ok(), "gte on integer should pass, got: {:?}", result.err());
|
||||
assert!(
|
||||
result.is_ok(),
|
||||
"gte on integer should pass, got: {:?}",
|
||||
result.err()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -2096,5 +2342,9 @@ workflow:
|
||||
gt: 5
|
||||
"#;
|
||||
let result = load_single_workflow_from_str(yaml, &HashMap::new());
|
||||
assert!(result.is_ok(), "any type should allow gt, got: {:?}", result.err());
|
||||
assert!(
|
||||
result.is_ok(),
|
||||
"any type should allow gt, got: {:?}",
|
||||
result.err()
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user