diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 33ba2b8..b5fc732 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -21,7 +21,7 @@ "commands": [ "dotnet-gitreleasemanager" ], - "rollForward": false + "rollForward": true } } -} \ No newline at end of file +} diff --git a/.github/workflows/NUnit.Cake.Recipe.CI.yml b/.github/workflows/NUnit.Cake.Recipe.CI.yml index 96e660b..643d9d3 100644 --- a/.github/workflows/NUnit.Cake.Recipe.CI.yml +++ b/.github/workflows/NUnit.Cake.Recipe.CI.yml @@ -39,13 +39,14 @@ jobs: - name: ๐Ÿ› ๏ธ Setup .NET uses: actions/setup-dotnet@v6 with: - dotnet-version: | - 8.0.x - 10.0.x + dotnet-version: 10.0.x - name: ๐Ÿ› ๏ธ Install dotnet tools run: dotnet tool restore + - name: ๐Ÿงช Check Release Tool Startup + run: dotnet tool run dotnet-gitreleasemanager -- showconfig --no-logo + - name: ๐Ÿงช Test Recipe Sources run: dotnet cake harness/tests.cake --target=Harness --packageVersion=1.0.0 --nopush diff --git a/.github/workflows/draft-release.yml b/.github/workflows/draft-release.yml index 5ae4fd9..9b85201 100644 --- a/.github/workflows/draft-release.yml +++ b/.github/workflows/draft-release.yml @@ -15,13 +15,14 @@ jobs: - name: ๐Ÿ› ๏ธ Setup .NET uses: actions/setup-dotnet@v6 with: - dotnet-version: | - 8.0.x - 7.0.x + dotnet-version: 10.0.x - name: ๐Ÿ› ๏ธ Install dotnet tools run: dotnet tool restore + - name: ๐Ÿงช Check Release Tool Startup + run: dotnet tool run dotnet-gitreleasemanager -- showconfig --no-logo + - name: ๐Ÿ”จ Create Draft Release env: GITHUB_ACCESS_TOKEN: ${{ secrets.GH_ACCESS_CP }} diff --git a/global.json b/global.json index 3fea262..ade3450 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "8.0.0", + "version": "10.0.0", "rollForward": "latestFeature" } } diff --git a/harness/README.md b/harness/README.md index 4b35589..83c5c6f 100644 --- a/harness/README.md +++ b/harness/README.md @@ -1,7 +1,7 @@ # Recipe source harness This harness loads `../recipe/*.cake` directly. No published recipe package or -copied implementation is used. It runs under the repository's .NET 8 SDK policy +copied implementation is used. It runs under the repository's .NET 10 SDK policy and pinned Cake.Tool 6.3.0, with Cake.Testing 6.3.0 for its test doubles. From the repository root: @@ -28,7 +28,7 @@ recipe's normal setup; no packaging or publishing target runs. | Target | Coverage | Report | | --- | --- | --- | | `Harness-Tests` | Deferred dependency checks, exact package IDs and versions, source/prerelease options, extension selectors, unresolved lookups, tool failures, unversioned checks and package-verification failure propagation | `harness/artifacts/tests.xml` | -| `Harness-Smoke` | Full source loading, recipe setup, Cake target execution and `PackageDefinition.VerifyPackage()` using actual filesystem/globbing operations, including an expected missing-file failure | `harness/artifacts/smoke.xml` | +| `Harness-Smoke` | Full source loading, recipe setup, Cake target execution, real filesystem package verification (including expected failure), and read-only startup of the Cake-installed release tool | `harness/artifacts/smoke.xml` | Reports use JUnit XML. Every behavior case runs before the target fails for any assertions. A failed target returns a nonzero exit code. Compilation/setup failures @@ -47,6 +47,12 @@ log and asserts both the exception and the specific error diagnostic. A successf run prints `Expected missing-file failure verified (payload.txt).` Unexpected exceptions or diagnostics still fail the target and appear in the XML report. +The release-tool smoke case executes only `showconfig --no-logo`; it performs no +release operation. Both CI workflows also check the local-manifest release tool +after restore. GitReleaseManager 0.20.0 still targets older runtimes, so its local +manifest enables roll-forward and recipe calls supply `DOTNET_ROLL_FORWARD=Major` +only to that tool's child process. No job-wide runtime override is used. + ## Regression history The original six diagnostic cases are represented here by deferred construction, diff --git a/harness/tests.cake b/harness/tests.cake index 3fd34ed..a17809d 100644 --- a/harness/tests.cake +++ b/harness/tests.cake @@ -26,6 +26,7 @@ Task("Harness-Smoke").Does(() => { var suite = new RecipeTestSuite(Context); suite.Add("real-cake/package-verification-and-failure", () => RunSmoke()); + suite.Add("real-cake/release-tool-startup", () => RunReleaseToolSmoke()); suite.Run("artifacts/smoke.xml"); }); Task("Harness").IsDependentOn("Harness-Tests").IsDependentOn("Harness-Smoke"); @@ -232,3 +233,25 @@ void RunSmoke() } HarnessAssert.True(!DirectoryExists(root), "smoke fixture cleanup"); } + +void RunReleaseToolSmoke() +{ + var executable = Context.Tools.Resolve(IsRunningOnWindows() + ? "dotnet-gitreleasemanager.exe" : "dotnet-gitreleasemanager"); + HarnessAssert.True(executable != null, "Cake-installed GitReleaseManager tool was not found"); + using (var process = Context.ProcessRunner.Start(executable, new ProcessSettings + { + Arguments = "showconfig --no-logo", + EnvironmentVariables = ReleaseManager.ToolEnvironment, + RedirectStandardOutput = true, + RedirectStandardError = true + })) + { + process.WaitForExit(); + string output = string.Join(Environment.NewLine, process.GetStandardOutput()); + string error = string.Join(Environment.NewLine, process.GetStandardError()); + HarnessAssert.Equal(0, process.GetExitCode(), "release-tool startup: " + error); + HarnessAssert.True(output.Contains("create:") && output.Contains("export:"), "release-tool configuration output"); + Information("Release-tool startup verified (read-only configuration)."); + } +} diff --git a/recipe/ReleaseManager.cake b/recipe/ReleaseManager.cake index 63867d2..780a124 100644 --- a/recipe/ReleaseManager.cake +++ b/recipe/ReleaseManager.cake @@ -7,6 +7,15 @@ public static class ReleaseManager _context = BuildSettings.Context; } + /// + /// Allows the pinned GitReleaseManager tool to run when only a newer major + /// runtime is installed. Apply only to that tool's child process. + /// + internal static IDictionary ToolEnvironment => new Dictionary + { + { "DOTNET_ROLL_FORWARD", "Major" } + }; + public static void Publish() { bool hadErrors = false; @@ -189,7 +198,8 @@ public static class ReleaseManager _context.GitReleaseManagerCreate(BuildSettings.GitHubAccessToken, BuildSettings.GitHubOwner, BuildSettings.GitHubRepository, new GitReleaseManagerCreateSettings() { Name = releaseName, - Milestone = releaseVersion + Milestone = releaseVersion, + EnvironmentVariables = ToolEnvironment }); } catch @@ -231,7 +241,8 @@ public static class ReleaseManager _context.GitReleaseManagerCreate(BuildSettings.GitHubAccessToken, BuildSettings.GitHubOwner, BuildSettings.GitHubRepository, new GitReleaseManagerCreateSettings() { Name = releaseName, - Milestone = releaseVersion + Milestone = releaseVersion, + EnvironmentVariables = ToolEnvironment }); } catch @@ -253,7 +264,7 @@ public static class ReleaseManager string milestone = BuildSettings.BranchName.Substring(8); _context.GitReleaseManagerExport(BuildSettings.GitHubAccessToken, BuildSettings.GitHubOwner, BuildSettings.GitHubRepository, "DraftRelease.md", - new GitReleaseManagerExportSettings() { TagName = milestone }); + new GitReleaseManagerExportSettings() { TagName = milestone, EnvironmentVariables = ToolEnvironment }); } public static void CreateProductionRelease() @@ -279,8 +290,10 @@ public static class ReleaseManager _context.Information($"Publishing release {tagName} to GitHub"); _context.Information($" Assets: {assets}"); - _context.GitReleaseManagerAddAssets(token, owner, repository, tagName, assets); - _context.GitReleaseManagerClose(token, owner, repository, tagName); + _context.GitReleaseManagerAddAssets(token, owner, repository, tagName, assets, + new GitReleaseManagerAddAssetsSettings() { EnvironmentVariables = ToolEnvironment }); + _context.GitReleaseManagerClose(token, owner, repository, tagName, + new GitReleaseManagerCloseMilestoneSettings() { EnvironmentVariables = ToolEnvironment }); } } }