diff options
| author | Melodi <62381002+Melodi17@users.noreply.github.com> | 2026-09-13 13:22:20 +1000 |
|---|---|---|
| committer | Melodi <62381002+Melodi17@users.noreply.github.com> | 2026-09-13 13:22:20 +1000 |
| commit | df0737e55afeb5c01eb39909605970d1d3a73ffc (patch) | |
| tree | 09823eaa310c60eefd2420dc305acae45c81900f /src/marlin.core/functional | |
| parent | ee69ce25b2fba871920260028bb10c2d6b62b26f (diff) | |
refactor: cleanup; feat: connection to agent
Diffstat (limited to 'src/marlin.core/functional')
| -rw-r--r-- | src/marlin.core/functional/WorkflowBuilder.cs | 153 | ||||
| -rw-r--r-- | src/marlin.core/functional/WorkflowJson.cs | 17 |
2 files changed, 170 insertions, 0 deletions
diff --git a/src/marlin.core/functional/WorkflowBuilder.cs b/src/marlin.core/functional/WorkflowBuilder.cs new file mode 100644 index 0000000..79da909 --- /dev/null +++ b/src/marlin.core/functional/WorkflowBuilder.cs @@ -0,0 +1,153 @@ +namespace marlin.core.functional; + +using models.meta; +using models.meta.dto; +using YamlDotNet.Serialization; +using YamlDotNet.Serialization.NamingConventions; + +public class WorkflowBuilder +{ + private static readonly IDeserializer Deserializer = new DeserializerBuilder() + .WithNamingConvention(HyphenatedNamingConvention.Instance) + .WithEnumNamingConvention(HyphenatedNamingConvention.Instance) + .IgnoreUnmatchedProperties() + .Build(); + + private readonly Workflow _workflow = new(); + + public Workflow Build() => this._workflow; + + public void LoadFromDirectory(string path) + { + var files = Directory.EnumerateFiles(path, "*.yml", SearchOption.AllDirectories); + + foreach (var file in files) + this.LoadFromString(File.ReadAllText(file)); + } + + public void LoadFromString(string content) + { + var file = Deserializer.Deserialize<WorkflowFileDto>(content); + if (file == null) + return; + + this.ApplyRequirements(file.Requirements); + this.ApplyRecipes(file.Recipes); + this.ApplySteps(file.Steps); + this.ApplyArtifactHandlers(file.ArtifactHandlers); + } + + private void ApplyRequirements(Dictionary<string, RequirementSetDto>? requirements) + { + if (requirements == null) + return; + + foreach (var (id, dto) in requirements) + { + var requirementSet = new RequirementSet(id) + { + Base = dto.Base, + Has = dto.Has != null ? new Dictionary<string, string>(dto.Has) : new() + }; + + this._workflow.Requirements[id] = requirementSet; + } + } + + private void ApplyRecipes(Dictionary<string, RecipeDto>? recipes) + { + if (recipes == null) + return; + + foreach (var (id, dto) in recipes) + { + var recipe = new Recipe(id) + { + Name = dto.Name ?? id, + RunsOnId = dto.RunsOn, + RequireIds = dto.Requires ?? [], + Parameters = dto.Parameters != null ? new Dictionary<string, string>(dto.Parameters) : new(), + Environment = dto.Environment != null ? new Dictionary<string, string>(dto.Environment) : new() + }; + + if (dto.Steps != null) + { + foreach (var (stepId, stepDto) in dto.Steps) + recipe.Steps[stepId] = this.BuildRecipeStep(stepId, stepDto); + } + + this._workflow.Recipes[id] = recipe; + } + } + + private void ApplySteps(Dictionary<string, StepDto>? steps) + { + if (steps == null) + return; + + foreach (var (id, dto) in steps) + this._workflow.Steps[id] = this.BuildRecipeStep(id, dto); + } + + private RecipeStep BuildRecipeStep(string id, StepDto dto) + { + var step = new RecipeStep(id); + ApplyAbstractStep(step, dto); + + step.BaseId = dto.Base; + step.Ingest = dto.Ingest ?? []; + + if (dto.Artifacts != null) + { + foreach (var (artifactId, artifactDto) in dto.Artifacts) + { + step.Artifacts[artifactId] = new Artifact(artifactId) + { + Path = artifactDto.Path!, + Type = artifactDto.As!, + Handle = artifactDto.Handle ?? ArtifactHandle.Defer + }; + } + } + + if (dto.Cleanup != null) + step.Cleanup = BuildCleanupStep(id + "/cleanup", dto.Cleanup); + + return step; + } + + private static CleanupStep BuildCleanupStep(string id, CleanupStepDto dto) + { + var step = new CleanupStep(id) { After = dto.After ?? CleanupAfter.Step }; + ApplyAbstractStep(step, dto); + return step; + } + + private void ApplyArtifactHandlers(Dictionary<string, ArtifactHandlerDto>? handlers) + { + if (handlers == null) + return; + + foreach (var (id, dto) in handlers) + { + var handler = new ArtifactHandler(id); + + if (dto.Handle != null) + { + var handleStep = new ArtifactHandlerStep(id + "/handle"); + ApplyAbstractStep(handleStep, dto.Handle); + handler.Handle = handleStep; + } + + this._workflow.ArtifactHandlers[id] = handler; + } + } + + private static void ApplyAbstractStep(AbstractStep step, StepDtoBase dto) + { + step.Name = dto.Name; + step.Run = dto.Run; + step.With = dto.With != null ? new Dictionary<string, string>(dto.With) : new(); + step.Fail = dto.Fail; + } +} diff --git a/src/marlin.core/functional/WorkflowJson.cs b/src/marlin.core/functional/WorkflowJson.cs new file mode 100644 index 0000000..011edae --- /dev/null +++ b/src/marlin.core/functional/WorkflowJson.cs @@ -0,0 +1,17 @@ +namespace marlin.core.functional; + +using System.Text.Json; +using System.Text.Json.Serialization; +using models.meta; + +public static class WorkflowJson +{ + private static readonly JsonSerializerOptions Options = new() + { + Converters = { new JsonStringEnumConverter() } + }; + + public static string Serialize(Workflow workflow) => JsonSerializer.Serialize(workflow, Options); + + public static Workflow Deserialize(string json) => JsonSerializer.Deserialize<Workflow>(json, Options)!; +} |
