From 338a7abd7c1bba0af9a7025e7c24a3e89dbb9085 Mon Sep 17 00:00:00 2001 From: Armin Graf Date: Thu, 11 Dec 2025 22:57:10 -0500 Subject: [PATCH 1/2] fix: align container and extension definitions to the spec Signed-off-by: Armin Graf --- core/src/lib.rs | 70 ++++++++++++++++++++++++++++++++++++ core/src/models/extension.rs | 5 ++- core/src/models/task.rs | 11 ++++-- core/src/models/workflow.rs | 2 +- 4 files changed, 82 insertions(+), 6 deletions(-) diff --git a/core/src/lib.rs b/core/src/lib.rs index 4306fc7..f66791a 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -373,4 +373,74 @@ mod unit_tests { assert!(script.environment.is_some()); assert_eq!(script.environment.as_ref().unwrap().get("FOO"), Some(&"bar".to_string())); } + + #[test] + fn test_extension_definition_serialization() { + let extension_json = json!({ + "document": { + "dsl": "1.0.2", + "namespace": "test", + "name": "sample-workflow", + "version": "0.1.0" + }, + "use": { + "extensions": [ + { + "mockService": { + "extend": "call", + "when": "($task.with.endpoint != null and ($task.with.endpoint | startswith(\"https://mocked.service.com\"))) or ($task.with.endpoint.uri != null and ($task.with.endpoint.uri | startswith(\"https://mocked.service.com\")))", + "before": [ + { + "mockResponse": { + "set": { + "statusCode": 200, + "headers": { + "Content-Type": "application/json" + }, + "content": { + "foo": { + "bar": "baz" + } + } + }, + "then": "exit" + } + } + ] + } + } + ] + }, + "do": [ + { + "callHttp": { + "call": "http", + "with": { + "method": "get", + "endpoint": { + "uri": "https://fake.com/sample" + } + } + } + } + ] + }); + let result: Result = serde_json::from_value(extension_json); + match result { + Ok(workflow) => { + // Verify the workflow was deserialized correctly + assert_eq!(workflow.document.namespace, "test"); + assert_eq!(workflow.document.name, "sample-workflow"); + assert_eq!(workflow.document.version, "0.1.0"); + // Verify the use section exists with extensions + assert!(workflow.use_.is_some()); + if let Some(use_def) = workflow.use_ { + assert!(use_def.extensions.is_some()); + } + } + Err(e) => { + panic!("Failed to deserialize workflow with extension: {}", e); + } + } + } } \ No newline at end of file diff --git a/core/src/models/extension.rs b/core/src/models/extension.rs index 241e3f9..4f55577 100644 --- a/core/src/models/extension.rs +++ b/core/src/models/extension.rs @@ -16,10 +16,9 @@ pub struct ExtensionDefinition{ /// Gets/sets a name/definition map, if any, of the tasks to execute before the extended task #[serde(rename = "before", skip_serializing_if = "Option::is_none")] - pub before: Option>, + pub before: Option>>, /// Gets/sets a name/definition map, if any, of the tasks to execute after the extended task #[serde(rename = "after", skip_serializing_if = "Option::is_none")] - pub after: Option> - + pub after: Option>> } \ No newline at end of file diff --git a/core/src/models/task.rs b/core/src/models/task.rs index 49e9dc9..489f3cb 100644 --- a/core/src/models/task.rs +++ b/core/src/models/task.rs @@ -715,16 +715,23 @@ pub struct ContainerProcessDefinition{ #[serde(rename = "environment", skip_serializing_if = "Option::is_none")] pub environment: Option>, + #[serde(rename = "stdin", skip_serializing_if = "Option::is_none")] + pub stdin: Option, + + #[serde(rename = "arguments", skip_serializing_if = "Option::is_none")] + pub arguments: Option>, } impl ContainerProcessDefinition { - pub fn new(image: &str, name: Option, command: Option, ports: Option>, volumes: Option>, environment: Option>) -> Self{ + pub fn new(image: &str, name: Option, command: Option, ports: Option>, volumes: Option>, environment: Option>, stdin: Option, arguments: Option>) -> Self{ Self { image: image.to_string(), name, command, ports, volumes, - environment + environment, + stdin, + arguments, } } } diff --git a/core/src/models/workflow.rs b/core/src/models/workflow.rs index 8493c7e..c19bf59 100644 --- a/core/src/models/workflow.rs +++ b/core/src/models/workflow.rs @@ -207,7 +207,7 @@ pub struct ComponentDefinitionCollection{ /// Gets/sets a name/value mapping of the workflow's extensions, if any #[serde(rename = "extensions", skip_serializing_if = "Option::is_none")] - pub extensions: Option>, + pub extensions: Option>>, /// Gets/sets a name/value mapping of the workflow's reusable functions #[serde(rename = "functions", skip_serializing_if = "Option::is_none")] From 77ac26b87a5733d3f72471953f61bb42a02d7e28 Mon Sep 17 00:00:00 2001 From: Armin Graf Date: Thu, 11 Dec 2025 23:06:54 -0500 Subject: [PATCH 2/2] fix: add correct comments Signed-off-by: Armin Graf --- core/src/models/extension.rs | 4 ++-- core/src/models/task.rs | 2 ++ core/src/models/workflow.rs | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/core/src/models/extension.rs b/core/src/models/extension.rs index 4f55577..5f80ed9 100644 --- a/core/src/models/extension.rs +++ b/core/src/models/extension.rs @@ -14,11 +14,11 @@ pub struct ExtensionDefinition{ #[serde(rename = "when", skip_serializing_if = "Option::is_none")] pub when: Option, - /// Gets/sets a name/definition map, if any, of the tasks to execute before the extended task + /// Gets/sets a name/definition list, if any, of the tasks to execute before the extended task #[serde(rename = "before", skip_serializing_if = "Option::is_none")] pub before: Option>>, - /// Gets/sets a name/definition map, if any, of the tasks to execute after the extended task + /// Gets/sets a name/definition list, if any, of the tasks to execute after the extended task #[serde(rename = "after", skip_serializing_if = "Option::is_none")] pub after: Option>> } \ No newline at end of file diff --git a/core/src/models/task.rs b/core/src/models/task.rs index 489f3cb..c80dc4a 100644 --- a/core/src/models/task.rs +++ b/core/src/models/task.rs @@ -715,9 +715,11 @@ pub struct ContainerProcessDefinition{ #[serde(rename = "environment", skip_serializing_if = "Option::is_none")] pub environment: Option>, + /// Gets/sets the data to pass to the process via stdin, if any #[serde(rename = "stdin", skip_serializing_if = "Option::is_none")] pub stdin: Option, + /// Gets/sets a list of arguments, if any, to pass to the container (argv) #[serde(rename = "arguments", skip_serializing_if = "Option::is_none")] pub arguments: Option>, } diff --git a/core/src/models/workflow.rs b/core/src/models/workflow.rs index c19bf59..6cfe0ce 100644 --- a/core/src/models/workflow.rs +++ b/core/src/models/workflow.rs @@ -205,7 +205,7 @@ pub struct ComponentDefinitionCollection{ #[serde(rename = "errors", skip_serializing_if = "Option::is_none")] pub errors: Option>, - /// Gets/sets a name/value mapping of the workflow's extensions, if any + /// Gets/sets a list containing the workflow's extensions, if any #[serde(rename = "extensions", skip_serializing_if = "Option::is_none")] pub extensions: Option>>,