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 });
}
}
}