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:
2026-04-07 18:44:21 +01:00
parent 3915bcc1ec
commit 02a574b24e
102 changed files with 2467 additions and 1307 deletions

View File

@@ -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:?}"),
}
}

View File

@@ -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;

View File

@@ -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));

View File

@@ -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}"

View File

@@ -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",
),
];

View File

@@ -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]

View File

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

View File

@@ -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() {

View File

@@ -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()
);
}