From bb84375432f7fac9e6cc13dd423127e030824a81 Mon Sep 17 00:00:00 2001 From: Declan Smith Date: Wed, 11 Feb 2026 10:25:30 +1000 Subject: [PATCH 1/3] fix(github-workflows): Fix dependabot options and generation Also added a test to ensure functionality. --- .github/dependabot.yml | 2 +- .../Workflows/DependabotBuild.cs | 28 +++++++ ...ndabotBuild_GeneratesWorkflow.verified.txt | 35 ++++++++ .../Workflows/WorkflowTests.cs | 29 +++++++ .../Generation/DependabotWorkflowWriter.cs | 81 ++++++++++--------- .../Generation/Options/DependabotOptions.cs | 2 +- 6 files changed, 138 insertions(+), 39 deletions(-) create mode 100644 DecSm.Atom.Module.GithubWorkflows.Tests/Workflows/DependabotBuild.cs create mode 100644 DecSm.Atom.Module.GithubWorkflows.Tests/Workflows/WorkflowTests.DependabotBuild_GeneratesWorkflow.verified.txt diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 743071e6..8ce0208f 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -15,7 +15,7 @@ updates: nuget-deps: patterns: - "*" - open-pull-requests-limit: 10 schedule: interval: daily + open-pull-requests-limit: 10 diff --git a/DecSm.Atom.Module.GithubWorkflows.Tests/Workflows/DependabotBuild.cs b/DecSm.Atom.Module.GithubWorkflows.Tests/Workflows/DependabotBuild.cs new file mode 100644 index 00000000..df11b6df --- /dev/null +++ b/DecSm.Atom.Module.GithubWorkflows.Tests/Workflows/DependabotBuild.cs @@ -0,0 +1,28 @@ +namespace DecSm.Atom.Module.GithubWorkflows.Tests.Workflows; + +[BuildDefinition] +public partial class DependabotBuild : MinimalBuildDefinition, IGithubWorkflows +{ + public override IReadOnlyList Workflows => + [ + Github.DependabotWorkflow(new() + { + Registries = [new("registry-1", "type1", "url1", "token1"), new("registry-2", "type2", "url2", "token2")], + Updates = + [ + new("update-1", "package-ecosystem-1", "directory-1", 1, DependabotSchedule.Daily) + { + Registries = ["registry-1", "registry-2"], + Groups = + [ + new("group-1") + { + Patterns = ["pattern-1", "pattern-2"], + }, + ], + }, + new("update-2", "package-ecosystem-2", "directory-2", 2, DependabotSchedule.Monthly), + ], + }), + ]; +} diff --git a/DecSm.Atom.Module.GithubWorkflows.Tests/Workflows/WorkflowTests.DependabotBuild_GeneratesWorkflow.verified.txt b/DecSm.Atom.Module.GithubWorkflows.Tests/Workflows/WorkflowTests.DependabotBuild_GeneratesWorkflow.verified.txt new file mode 100644 index 00000000..aaa3e6e9 --- /dev/null +++ b/DecSm.Atom.Module.GithubWorkflows.Tests/Workflows/WorkflowTests.DependabotBuild_GeneratesWorkflow.verified.txt @@ -0,0 +1,35 @@ +version: 2 + +registries: + registry-1: + type: nuget-feed + url: url1 + token: ${{token1}} + registry-2: + type: nuget-feed + url: url2 + token: ${{token2}} + +updates: + - package-ecosystem: "update-1" + target-branch: "package-ecosystem-1" + directory: "directory-1" + registries: + - registry-1 + - registry-2 + groups: + group-1: + patterns: + - "pattern-1" + - "pattern-2" + schedule: + interval: + daily + open-pull-requests-limit: 1 + - package-ecosystem: "update-2" + target-branch: "package-ecosystem-2" + directory: "directory-2" + schedule: + interval: + monthly + open-pull-requests-limit: 2 diff --git a/DecSm.Atom.Module.GithubWorkflows.Tests/Workflows/WorkflowTests.cs b/DecSm.Atom.Module.GithubWorkflows.Tests/Workflows/WorkflowTests.cs index 7af210ff..090ca28f 100644 --- a/DecSm.Atom.Module.GithubWorkflows.Tests/Workflows/WorkflowTests.cs +++ b/DecSm.Atom.Module.GithubWorkflows.Tests/Workflows/WorkflowTests.cs @@ -8,6 +8,11 @@ Environment.OSVersion.Platform is PlatformID.Win32NT ? @"C:\Atom\.github\workflows\" : "/Atom/.github/workflows/"; + private static string DependabotDir => + Environment.OSVersion.Platform is PlatformID.Win32NT + ? @"C:\Atom\.github\" + : "/Atom/.github/"; + [Test] public void MinimalBuild_GeneratesNoWorkflows() { @@ -436,4 +441,28 @@ public async Task GithubCustomStepBuild_GeneratesWorkflow() await Verify(workflow); await TestContext.Out.WriteAsync(workflow); } + + [Test] + public async Task DependabotBuild_GeneratesWorkflow() + { + // Arrange + var fileSystem = FileSystemUtils.DefaultMockFileSystem; + + var build = CreateTestHost(fileSystem: fileSystem, commandLineArgs: new(true, [new GenArg()])); + + // Act + await build.RunAsync(); + + // Assert + fileSystem + .DirectoryInfo + .New(DependabotDir) + .Exists + .ShouldBeTrue(); + + var workflow = await fileSystem.File.ReadAllTextAsync($"{DependabotDir}dependabot.yml"); + + await Verify(workflow); + await TestContext.Out.WriteAsync(workflow); + } } diff --git a/DecSm.Atom.Module.GithubWorkflows/Generation/DependabotWorkflowWriter.cs b/DecSm.Atom.Module.GithubWorkflows/Generation/DependabotWorkflowWriter.cs index 96cceac7..bb6c82ae 100644 --- a/DecSm.Atom.Module.GithubWorkflows/Generation/DependabotWorkflowWriter.cs +++ b/DecSm.Atom.Module.GithubWorkflows/Generation/DependabotWorkflowWriter.cs @@ -20,51 +20,56 @@ protected override void WriteWorkflow(WorkflowModel workflow) WriteLine("version: 2"); - if (dependabot.Registries.Count == 0) - return; - - WriteLine(); - - using (WriteSection("registries:")) + if (dependabot.Registries.Count > 0) { - foreach (var registry in dependabot.Registries) - using (WriteSection($"{registry.Name}:")) - { - WriteLine("type: nuget-feed"); - WriteLine($"url: {registry.Url}"); + WriteLine(); - if (registry.Token is not null) - WriteLine($"token: ${{{{{registry.Token}}}}}"); - } - } + using (WriteSection("registries:")) + { + foreach (var registry in dependabot.Registries) + using (WriteSection($"{registry.Name}:")) + { + WriteLine("type: nuget-feed"); + WriteLine($"url: {registry.Url}"); - WriteLine(); + if (registry.Token is not null) + WriteLine($"token: ${{{{{registry.Token}}}}}"); + } + } + } - using (WriteSection("updates:")) + if (dependabot.Updates.Count > 0) { - foreach (var update in dependabot.Updates) - using (WriteSection("- package-ecosystem: \"nuget\"")) - { - WriteLine($"target-branch: \"{update.TargetBranch}\""); - WriteLine("directory: \"/\""); + WriteLine(); - if (dependabot.Registries.Count != 0) + using (WriteSection("updates:")) + { + foreach (var update in dependabot.Updates) + using (WriteSection($"- package-ecosystem: \"{update.Ecosystem}\"")) { - WriteLine("registries:"); + WriteLine($"target-branch: \"{update.TargetBranch}\""); + WriteLine($"directory: \"{update.Directory}\""); - foreach (var registry in dependabot.Registries) - WriteLine($" - {registry.Name}"); - } - - using (WriteSection("groups:")) - using (WriteSection("nuget-deps:")) - using (WriteSection("patterns:")) - WriteLine("- \"*\""); - - WriteLine($"open-pull-requests-limit: {update.OpenPullRequestsLimit}"); + if (update.Registries.Count > 0) + using (WriteSection("registries:")) + { + foreach (var registry in update.Registries) + WriteLine($"- {registry}"); + } - using (WriteSection("schedule:")) - { + if (update.Groups.Count > 0) + using (WriteSection("groups:")) + { + foreach (var group in update.Groups) + using (WriteSection($"{group.Name}:")) + using (WriteSection("patterns:")) + { + foreach (var pattern in group.Patterns ?? []) + WriteLine($"- \"{pattern}\""); + } + } + + using (WriteSection("schedule:")) using (WriteSection("interval:")) { WriteLine(update.Schedule switch @@ -77,8 +82,10 @@ protected override void WriteWorkflow(WorkflowModel workflow) $"Dependabot schedule '{update.Schedule}' is not supported."), }); } + + WriteLine($"open-pull-requests-limit: {update.OpenPullRequestsLimit}"); } - } + } } } } diff --git a/DecSm.Atom.Module.GithubWorkflows/Generation/Options/DependabotOptions.cs b/DecSm.Atom.Module.GithubWorkflows/Generation/Options/DependabotOptions.cs index 4cb773e5..8095658e 100644 --- a/DecSm.Atom.Module.GithubWorkflows/Generation/Options/DependabotOptions.cs +++ b/DecSm.Atom.Module.GithubWorkflows/Generation/Options/DependabotOptions.cs @@ -20,7 +20,7 @@ public sealed record DependabotUpdate( DependabotSchedule Schedule = DependabotSchedule.Weekly ) { - public required IReadOnlyCollection Registries { get; init; } = []; + public IReadOnlyCollection Registries { get; init; } = []; public IReadOnlyCollection Groups { get; init; } = []; } From c0ab9a45b077b3770ff89645f2ec77e3d74dee02 Mon Sep 17 00:00:00 2001 From: Declan Smith Date: Wed, 11 Feb 2026 10:53:01 +1000 Subject: [PATCH 2/3] fix(workflows): fix dynamic registry type generation in Dependabot Updated `DependabotWorkflowWriter` to generate registry types dynamically based on registry configuration. Adjusted tests to verify the change. --- ...rkflowTests.DependabotBuild_GeneratesWorkflow.verified.txt | 4 ++-- .../Generation/DependabotWorkflowWriter.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/DecSm.Atom.Module.GithubWorkflows.Tests/Workflows/WorkflowTests.DependabotBuild_GeneratesWorkflow.verified.txt b/DecSm.Atom.Module.GithubWorkflows.Tests/Workflows/WorkflowTests.DependabotBuild_GeneratesWorkflow.verified.txt index aaa3e6e9..64ff9a0a 100644 --- a/DecSm.Atom.Module.GithubWorkflows.Tests/Workflows/WorkflowTests.DependabotBuild_GeneratesWorkflow.verified.txt +++ b/DecSm.Atom.Module.GithubWorkflows.Tests/Workflows/WorkflowTests.DependabotBuild_GeneratesWorkflow.verified.txt @@ -2,11 +2,11 @@ registries: registry-1: - type: nuget-feed + type: type1 url: url1 token: ${{token1}} registry-2: - type: nuget-feed + type: type2 url: url2 token: ${{token2}} diff --git a/DecSm.Atom.Module.GithubWorkflows/Generation/DependabotWorkflowWriter.cs b/DecSm.Atom.Module.GithubWorkflows/Generation/DependabotWorkflowWriter.cs index bb6c82ae..d43bee96 100644 --- a/DecSm.Atom.Module.GithubWorkflows/Generation/DependabotWorkflowWriter.cs +++ b/DecSm.Atom.Module.GithubWorkflows/Generation/DependabotWorkflowWriter.cs @@ -29,7 +29,7 @@ protected override void WriteWorkflow(WorkflowModel workflow) foreach (var registry in dependabot.Registries) using (WriteSection($"{registry.Name}:")) { - WriteLine("type: nuget-feed"); + WriteLine($"type: {registry.Type}"); WriteLine($"url: {registry.Url}"); if (registry.Token is not null) From 40ec2739e2b5964f520ecbe4310251785ad5da05 Mon Sep 17 00:00:00 2001 From: Declan Smith Date: Wed, 11 Feb 2026 10:56:23 +1000 Subject: [PATCH 3/3] fix(workflows): skip empty patterns in Dependabot group generation Ensured `DependabotWorkflowWriter` correctly skips groups with empty or null patterns during workflow generation. Prevented unnecessary "patterns:" section writing for such cases, improving output clarity. --- .../Generation/DependabotWorkflowWriter.cs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/DecSm.Atom.Module.GithubWorkflows/Generation/DependabotWorkflowWriter.cs b/DecSm.Atom.Module.GithubWorkflows/Generation/DependabotWorkflowWriter.cs index d43bee96..4237dde4 100644 --- a/DecSm.Atom.Module.GithubWorkflows/Generation/DependabotWorkflowWriter.cs +++ b/DecSm.Atom.Module.GithubWorkflows/Generation/DependabotWorkflowWriter.cs @@ -62,10 +62,15 @@ protected override void WriteWorkflow(WorkflowModel workflow) { foreach (var group in update.Groups) using (WriteSection($"{group.Name}:")) - using (WriteSection("patterns:")) { - foreach (var pattern in group.Patterns ?? []) - WriteLine($"- \"{pattern}\""); + if (group.Patterns is not { Count: > 0 }) + continue; + + using (WriteSection("patterns:")) + { + foreach (var pattern in group.Patterns) + WriteLine($"- \"{pattern}\""); + } } }