From 4189eaf08f270a1836f48c99d161e6635bce3061 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 20 Sep 2025 16:14:22 +0000 Subject: [PATCH 1/5] Initial plan From 7d6ac7873c0f09ea3f3eae0916d7fd4637f4b4c6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 20 Sep 2025 16:26:56 +0000 Subject: [PATCH 2/5] Fix YAML deserializer to bind inherited properties in custom step types Co-authored-by: danielgerlag <2357007+danielgerlag@users.noreply.github.com> --- .../Services/DefinitionLoader.cs | 2 +- .../DataTypes/CounterBoard.cs | 2 + .../Steps/IterateListStep.cs | 12 +++ .../YamlInheritedPropertyIntegrationTest.cs | 75 +++++++++++++++++++ 4 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 test/WorkflowCore.TestAssets/Steps/IterateListStep.cs create mode 100644 test/WorkflowCore.UnitTests/Services/DefinitionStorage/YamlInheritedPropertyIntegrationTest.cs diff --git a/src/WorkflowCore.DSL/Services/DefinitionLoader.cs b/src/WorkflowCore.DSL/Services/DefinitionLoader.cs index aa22988eb..bd8314bad 100644 --- a/src/WorkflowCore.DSL/Services/DefinitionLoader.cs +++ b/src/WorkflowCore.DSL/Services/DefinitionLoader.cs @@ -222,7 +222,7 @@ private void AttachInputs(StepSourceV1 source, Type dataType, Type stepType, Wor var dataParameter = Expression.Parameter(dataType, "data"); var contextParameter = Expression.Parameter(typeof(IStepExecutionContext), "context"); var environmentVarsParameter = Expression.Parameter(typeof(IDictionary), "environment"); - var stepProperty = stepType.GetProperty(input.Key); + var stepProperty = stepType.GetProperty(input.Key, BindingFlags.Public | BindingFlags.Instance); if (stepProperty == null) { diff --git a/test/WorkflowCore.TestAssets/DataTypes/CounterBoard.cs b/test/WorkflowCore.TestAssets/DataTypes/CounterBoard.cs index a93b43585..d7c03c2d7 100644 --- a/test/WorkflowCore.TestAssets/DataTypes/CounterBoard.cs +++ b/test/WorkflowCore.TestAssets/DataTypes/CounterBoard.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; namespace WorkflowCore.TestAssets.DataTypes { @@ -17,5 +18,6 @@ public class CounterBoard public bool Flag1 { get; set; } public bool Flag2 { get; set; } public bool Flag3 { get; set; } + public List DataList { get; set; } = new List { "item1", "item2", "item3" }; } } diff --git a/test/WorkflowCore.TestAssets/Steps/IterateListStep.cs b/test/WorkflowCore.TestAssets/Steps/IterateListStep.cs new file mode 100644 index 000000000..77e9069f0 --- /dev/null +++ b/test/WorkflowCore.TestAssets/Steps/IterateListStep.cs @@ -0,0 +1,12 @@ +using WorkflowCore.Interface; +using WorkflowCore.Models; +using WorkflowCore.Primitives; + +namespace WorkflowCore.TestAssets.Steps +{ + public class IterateListStep : Foreach + { + // This class inherits from Foreach and should be able to use + // the RunParallel property from the base class in YAML definitions + } +} \ No newline at end of file diff --git a/test/WorkflowCore.UnitTests/Services/DefinitionStorage/YamlInheritedPropertyIntegrationTest.cs b/test/WorkflowCore.UnitTests/Services/DefinitionStorage/YamlInheritedPropertyIntegrationTest.cs new file mode 100644 index 000000000..72237d3a8 --- /dev/null +++ b/test/WorkflowCore.UnitTests/Services/DefinitionStorage/YamlInheritedPropertyIntegrationTest.cs @@ -0,0 +1,75 @@ +using System; +using System.Collections.Generic; +using WorkflowCore.Interface; +using WorkflowCore.Services.DefinitionStorage; +using Xunit; + +namespace WorkflowCore.UnitTests.Services.DefinitionStorage +{ + /// + /// Integration test to verify the fix for inherited property binding in YAML definitions. + /// This test specifically reproduces the issue mentioned in GitHub issue #1375. + /// + public class YamlInheritedPropertyIntegrationTest + { + [Fact(DisplayName = "Should bind inherited properties like RunParallel from base Foreach class")] + public void ShouldBindInheritedPropertiesInYamlDefinition() + { + // Arrange + var registry = new WorkflowRegistry(); + var loader = new DefinitionLoader(registry, new TypeResolver()); + + // This YAML definition uses a custom step (IterateListStep) that inherits from Foreach + // and tries to set the RunParallel property which is defined in the base Foreach class + var yamlWithInheritedProperty = @" +Id: TestInheritedPropertyWorkflow +Version: 1 +Description: Test workflow for inherited property binding +DataType: WorkflowCore.TestAssets.DataTypes.CounterBoard, WorkflowCore.TestAssets +Steps: + - Id: IterateList + StepType: WorkflowCore.TestAssets.Steps.IterateListStep, WorkflowCore.TestAssets + Inputs: + Collection: ""data.DataList"" + RunParallel: false +"; + + // Act & Assert + // Before the fix, this would throw: "Unknown property for input RunParallel on IterateList" + // After the fix, this should succeed + var exception = Record.Exception(() => + loader.LoadDefinition(yamlWithInheritedProperty, Deserializers.Yaml)); + + // Verify no exception was thrown + Assert.Null(exception); + } + + [Fact(DisplayName = "Should still throw exception for truly unknown properties")] + public void ShouldStillThrowForUnknownProperties() + { + // Arrange + var registry = new WorkflowRegistry(); + var loader = new DefinitionLoader(registry, new TypeResolver()); + + var yamlWithUnknownProperty = @" +Id: TestInheritedPropertyWorkflow +Version: 1 +Description: Test workflow for inherited property binding +DataType: WorkflowCore.TestAssets.DataTypes.CounterBoard, WorkflowCore.TestAssets +Steps: + - Id: IterateList + StepType: WorkflowCore.TestAssets.Steps.IterateListStep, WorkflowCore.TestAssets + Inputs: + Collection: ""data.DataList"" + NonExistentProperty: false +"; + + // Act & Assert + // This should still throw an exception for truly unknown properties + var exception = Assert.Throws(() => + loader.LoadDefinition(yamlWithUnknownProperty, Deserializers.Yaml)); + + Assert.Contains("Unknown property for input NonExistentProperty", exception.Message); + } + } +} \ No newline at end of file From d4d385d2d1024e2797296ed63777e33d955e5b46 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 20 Sep 2025 16:55:58 +0000 Subject: [PATCH 3/5] Fix build issue: Update test to use FakeItEasy mock for IWorkflowRegistry Co-authored-by: danielgerlag <2357007+danielgerlag@users.noreply.github.com> --- .../YamlInheritedPropertyIntegrationTest.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/WorkflowCore.UnitTests/Services/DefinitionStorage/YamlInheritedPropertyIntegrationTest.cs b/test/WorkflowCore.UnitTests/Services/DefinitionStorage/YamlInheritedPropertyIntegrationTest.cs index 72237d3a8..f036851f2 100644 --- a/test/WorkflowCore.UnitTests/Services/DefinitionStorage/YamlInheritedPropertyIntegrationTest.cs +++ b/test/WorkflowCore.UnitTests/Services/DefinitionStorage/YamlInheritedPropertyIntegrationTest.cs @@ -1,5 +1,5 @@ using System; -using System.Collections.Generic; +using FakeItEasy; using WorkflowCore.Interface; using WorkflowCore.Services.DefinitionStorage; using Xunit; @@ -16,7 +16,7 @@ public class YamlInheritedPropertyIntegrationTest public void ShouldBindInheritedPropertiesInYamlDefinition() { // Arrange - var registry = new WorkflowRegistry(); + var registry = A.Fake(); var loader = new DefinitionLoader(registry, new TypeResolver()); // This YAML definition uses a custom step (IterateListStep) that inherits from Foreach @@ -48,7 +48,7 @@ public void ShouldBindInheritedPropertiesInYamlDefinition() public void ShouldStillThrowForUnknownProperties() { // Arrange - var registry = new WorkflowRegistry(); + var registry = A.Fake(); var loader = new DefinitionLoader(registry, new TypeResolver()); var yamlWithUnknownProperty = @" From 4cb4c84348aa3c1d56e51e65d8846ec07476f1eb Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 5 Oct 2025 02:58:29 +0000 Subject: [PATCH 4/5] Fix test: Use string value for RunParallel in YAML and add Static binding flag Co-authored-by: danielgerlag <2357007+danielgerlag@users.noreply.github.com> --- src/WorkflowCore.DSL/Services/DefinitionLoader.cs | 2 +- .../DefinitionStorage/YamlInheritedPropertyIntegrationTest.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/WorkflowCore.DSL/Services/DefinitionLoader.cs b/src/WorkflowCore.DSL/Services/DefinitionLoader.cs index bd8314bad..fb6459546 100644 --- a/src/WorkflowCore.DSL/Services/DefinitionLoader.cs +++ b/src/WorkflowCore.DSL/Services/DefinitionLoader.cs @@ -222,7 +222,7 @@ private void AttachInputs(StepSourceV1 source, Type dataType, Type stepType, Wor var dataParameter = Expression.Parameter(dataType, "data"); var contextParameter = Expression.Parameter(typeof(IStepExecutionContext), "context"); var environmentVarsParameter = Expression.Parameter(typeof(IDictionary), "environment"); - var stepProperty = stepType.GetProperty(input.Key, BindingFlags.Public | BindingFlags.Instance); + var stepProperty = stepType.GetProperty(input.Key, BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static); if (stepProperty == null) { diff --git a/test/WorkflowCore.UnitTests/Services/DefinitionStorage/YamlInheritedPropertyIntegrationTest.cs b/test/WorkflowCore.UnitTests/Services/DefinitionStorage/YamlInheritedPropertyIntegrationTest.cs index f036851f2..a782e3c65 100644 --- a/test/WorkflowCore.UnitTests/Services/DefinitionStorage/YamlInheritedPropertyIntegrationTest.cs +++ b/test/WorkflowCore.UnitTests/Services/DefinitionStorage/YamlInheritedPropertyIntegrationTest.cs @@ -31,7 +31,7 @@ public void ShouldBindInheritedPropertiesInYamlDefinition() StepType: WorkflowCore.TestAssets.Steps.IterateListStep, WorkflowCore.TestAssets Inputs: Collection: ""data.DataList"" - RunParallel: false + RunParallel: ""false"" "; // Act & Assert From d3ab802460ce7a7bf40b281ac9e5fc3504aa8917 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 5 Oct 2025 04:04:21 +0000 Subject: [PATCH 5/5] Properly handle primitive values (bool, int, etc.) in YAML inputs without quoting Co-authored-by: danielgerlag <2357007+danielgerlag@users.noreply.github.com> --- src/WorkflowCore.DSL/Services/DefinitionLoader.cs | 15 +++++++++++++++ .../YamlInheritedPropertyIntegrationTest.cs | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/WorkflowCore.DSL/Services/DefinitionLoader.cs b/src/WorkflowCore.DSL/Services/DefinitionLoader.cs index fb6459546..64826f508 100644 --- a/src/WorkflowCore.DSL/Services/DefinitionLoader.cs +++ b/src/WorkflowCore.DSL/Services/DefinitionLoader.cs @@ -243,6 +243,21 @@ private void AttachInputs(StepSourceV1 source, Type dataType, Type stepType, Wor continue; } + // Handle primitive values (bool, int, etc.) directly + if (input.Value != null && (input.Value.GetType().IsPrimitive || input.Value is bool || input.Value is int || input.Value is long || input.Value is double || input.Value is decimal)) + { + var primitiveValue = input.Value; + void primitiveAction(IStepBody pStep, object pData) + { + if (stepProperty.PropertyType.IsAssignableFrom(primitiveValue.GetType())) + stepProperty.SetValue(pStep, primitiveValue); + else + stepProperty.SetValue(pStep, System.Convert.ChangeType(primitiveValue, stepProperty.PropertyType)); + } + step.Inputs.Add(new ActionParameter(primitiveAction)); + continue; + } + throw new ArgumentException($"Unknown type for input {input.Key} on {source.Id}"); } } diff --git a/test/WorkflowCore.UnitTests/Services/DefinitionStorage/YamlInheritedPropertyIntegrationTest.cs b/test/WorkflowCore.UnitTests/Services/DefinitionStorage/YamlInheritedPropertyIntegrationTest.cs index a782e3c65..f036851f2 100644 --- a/test/WorkflowCore.UnitTests/Services/DefinitionStorage/YamlInheritedPropertyIntegrationTest.cs +++ b/test/WorkflowCore.UnitTests/Services/DefinitionStorage/YamlInheritedPropertyIntegrationTest.cs @@ -31,7 +31,7 @@ public void ShouldBindInheritedPropertiesInYamlDefinition() StepType: WorkflowCore.TestAssets.Steps.IterateListStep, WorkflowCore.TestAssets Inputs: Collection: ""data.DataList"" - RunParallel: ""false"" + RunParallel: false "; // Act & Assert