Skip to content

Commit 6e2d880

Browse files
authored
Merge pull request #10 from viamus/feature/pipeline-composition
Add use_pipeline step type for pipeline composition
2 parents 22fc73a + 2ab698c commit 6e2d880

18 files changed

Lines changed: 1227 additions & 20 deletions

.github/workflows/ci.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,7 @@ jobs:
1616
- name: Setup .NET
1717
uses: actions/setup-dotnet@v4
1818
with:
19-
dotnet-version: 10.0.x
20-
dotnet-quality: preview
19+
dotnet-version: 10.0.103
2120

2221
- name: Restore dependencies
2322
run: dotnet restore

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,8 @@ docker-compose.override.yml
118118
publish/
119119
out/
120120
artifacts/
121+
*.pubxml
122+
*.pubxml.user
121123

122124
##############################
123125
# Coverage tools

CodeGenesis.Engine.Tests/Config/PipelineConfigLoaderTests.cs

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,93 @@ public void LoadFromFile_ParallelMissingBranches_ThrowsInvalidOperation()
259259
}
260260
}
261261

262+
[Fact]
263+
public void LoadFromFile_UsePipelineStep_ParsesCorrectly()
264+
{
265+
var yaml = """
266+
pipeline:
267+
name: Composition Test
268+
steps:
269+
- name: Run child
270+
use_pipeline: ./child.yml
271+
inputs:
272+
source: "some value"
273+
output_key: child_result
274+
""";
275+
276+
var path = Path.Combine(Path.GetTempPath(), $"test-{Guid.NewGuid()}.yaml");
277+
File.WriteAllText(path, yaml);
278+
try
279+
{
280+
var config = PipelineConfigLoader.LoadFromFile(path);
281+
282+
config.Steps.Should().HaveCount(1);
283+
config.Steps[0].IsUsePipeline.Should().BeTrue();
284+
config.Steps[0].IsSimpleStep.Should().BeFalse();
285+
config.Steps[0].Name.Should().Be("Run child");
286+
config.Steps[0].UsePipeline.Should().Be("./child.yml");
287+
config.Steps[0].Inputs.Should().ContainKey("source");
288+
config.Steps[0].Inputs!["source"].Should().Be("some value");
289+
config.Steps[0].OutputKey.Should().Be("child_result");
290+
}
291+
finally
292+
{
293+
File.Delete(path);
294+
}
295+
}
296+
297+
[Fact]
298+
public void LoadFromFile_UsePipelineMissingName_ThrowsInvalidOperation()
299+
{
300+
var yaml = """
301+
pipeline:
302+
name: Bad
303+
steps:
304+
- use_pipeline: ./child.yml
305+
""";
306+
307+
var path = Path.Combine(Path.GetTempPath(), $"test-{Guid.NewGuid()}.yaml");
308+
File.WriteAllText(path, yaml);
309+
try
310+
{
311+
var act = () => PipelineConfigLoader.LoadFromFile(path);
312+
313+
act.Should().Throw<InvalidOperationException>()
314+
.WithMessage("*missing a 'name'*");
315+
}
316+
finally
317+
{
318+
File.Delete(path);
319+
}
320+
}
321+
322+
[Fact]
323+
public void LoadFromFile_UsePipelineWithOptional_ParsesCorrectly()
324+
{
325+
var yaml = """
326+
pipeline:
327+
name: Optional Test
328+
steps:
329+
- name: Optional child
330+
use_pipeline: ./child.yml
331+
optional: true
332+
""";
333+
334+
var path = Path.Combine(Path.GetTempPath(), $"test-{Guid.NewGuid()}.yaml");
335+
File.WriteAllText(path, yaml);
336+
try
337+
{
338+
var config = PipelineConfigLoader.LoadFromFile(path);
339+
340+
config.Steps[0].IsUsePipeline.Should().BeTrue();
341+
config.Steps[0].Optional.Should().BeTrue();
342+
}
343+
finally
344+
{
345+
File.Delete(path);
346+
}
347+
}
348+
262349
[Fact]
263350
public void LoadFromFile_WithInputsAndOutputs_ParsesCorrectly()
264351
{

CodeGenesis.Engine.Tests/Config/StepEntryTests.cs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,41 @@ public void IsApproval_WithConfig_ReturnsTrue()
6565
entry.IsSimpleStep.Should().BeFalse();
6666
}
6767

68+
[Fact]
69+
public void IsUsePipeline_WithUsePipeline_ReturnsTrue()
70+
{
71+
var entry = new StepEntry
72+
{
73+
Name = "sub",
74+
UsePipeline = "./child.yml"
75+
};
76+
77+
entry.IsUsePipeline.Should().BeTrue();
78+
entry.IsSimpleStep.Should().BeFalse();
79+
entry.IsForeach.Should().BeFalse();
80+
entry.IsParallel.Should().BeFalse();
81+
}
82+
83+
[Fact]
84+
public void IsUsePipeline_WithoutUsePipeline_ReturnsFalse()
85+
{
86+
var entry = new StepEntry { Name = "step1", Prompt = "do something" };
87+
88+
entry.IsUsePipeline.Should().BeFalse();
89+
}
90+
91+
[Fact]
92+
public void IsSimpleStep_WithUsePipeline_ReturnsFalse()
93+
{
94+
var entry = new StepEntry
95+
{
96+
Name = "sub",
97+
UsePipeline = "./child.yml"
98+
};
99+
100+
entry.IsSimpleStep.Should().BeFalse();
101+
}
102+
68103
[Fact]
69104
public void IsSimpleStep_NullNameNoComposite_ReturnsFalse()
70105
{

0 commit comments

Comments
 (0)