Skip to content

Drop .NET 8 and .NET 9 target frameworks (end of support 2026-11-10) #4997

Description

@arturcic

Summary

Drop the .NET 8 and .NET 9 target frameworks and consolidate GitVersion on .NET 10 (LTS), following the .NET 8 & 9 end-of-support announcement.

Per the announcement:

Runtime Track End of support
.NET 9 STS November 10, 2026
.NET 8 LTS November 10, 2026
.NET 10 LTS November 2028 ✅

GitVersion currently multi-targets net8.0;net9.0;net10.0. Both .NET 8 and .NET 9 reach end of life on November 10, 2026, so 7.x (a major release) is the right time to drop both and target the current LTS, .NET 10, only.

⚠️ Breaking change

  • The CLI / global tool will require the .NET 10 runtime.
  • GitVersion.MsBuild will ship only tools/net10.0. Consumers building net8.0/net9.0 projects will run the task via the existing dotnet --roll-forward Major shim (see GitVersion.MsBuild.targets), so a .NET 10 runtime must be available in the build environment. This should be verified as part of the work.
  • Per-framework Docker images for 8.0/9.0 will no longer be produced.

What needs to change

Target frameworks

  • src/Directory.Build.props:3<TargetFrameworks>net8.0;net9.0;net10.0</TargetFrameworks><TargetFramework>net10.0</TargetFramework>
  • src/Directory.Packages.props:6-8 — remove the net8.0 (17.11.48) and net9.0 (17.14.28) MicrosoftBuildVersion conditions; keep only the net10.0 value (18.7.1), which can then be unconditional

Source code (framework-conditional compilation)

  • src/GitVersion.Core/Core/RegexPatterns.cs47 #if NET9_0_OR_GREATER / #else / #endif blocks. The net9.0+ branch uses the partial-property [GeneratedRegex] form (public static partial Regex X { get; }); the net8.0 #else branch uses the older method form (private static partial Regex XImpl(); public static Regex X { get; } = XImpl();) because net8.0's regex source generator doesn't support partial properties. Once net8.0 is gone, every #if NET9_0_OR_GREATER is always true — keep the partial-property branch and delete all 47 #else branches plus the #if/#else/#endif directives. This is the only source file with TFM-conditional compilation (verified via grep -rE "#if .*NET[0-9]" src new-cli).

MSBuild task packaging & selection

  • src/GitVersion.MsBuild/GitVersion.MsBuild.csproj:42-43 — remove the tools/net8.0 and tools/net9.0 <None Include=.../> packaging entries (keep tools/net10.0 at :44)
  • src/GitVersion.MsBuild/msbuild/tools/GitVersion.MsBuild.targets:12-16 — remove the net8.0 and net9.0 GitVersionTargetFramework selection branches; keep the net10.0 branch and make the fallback resolve to net10.0 (currently falls back to net8.0)

Build / CI matrix (drives test jobs and Docker images)

  • build/common/Utilities/Constants.cs:10DotnetVersions = [DotnetLtsLatest, "9.0", "8.0"][DotnetLtsLatest] (i.e. just "10.0"). This single constant feeds:
    • the CI unit-test matrix via build/config/Tasks/SetMatrix.cs_prepare.yml dotnet_versions → the Test / <os> - net8.0|net9.0|net10.0 jobs in ci.yml/_unit_tests.yml
    • the Docker image matrix via build/common/Lifetime/DockerBuildLifetime.cs:28,52
  • Confirm no remaining hard-coded net8.0/net9.0 assumptions in build/artifacts/Tasks/ArtifactsMsBuild*Test.cs and the docker tasks once the matrix is reduced

Verification

  • grep -rn "net8\.0\|net9\.0" src new-cli build .github returns nothing meaningful (only intentional history/notes, if any)
  • grep -rn "#if .*NET[0-9]" src new-cli returns nothing (all TFM-conditional compilation removed)
  • dotnet build ./src/GitVersion.slnx and ./new-cli/GitVersion.slnx build on net10.0 only
  • dotnet test ./src/GitVersion.slnx is green (matrix now net10.0 only)
  • dotnet format --verify-no-changes ./src/GitVersion.slnx passes
  • GitVersion.MsBuild smoke-tested against a consumer project targeting net8.0 (must still work via roll-forward to the net10.0 tools)
  • Docker build produces only net10.0 images
  • Docs / README updated if any supported-runtime matrix is published; CHANGELOG notes the breaking change

Notes

  • The SDK is already 10.0.301 (global.json), so the toolchain is ready.
  • MicrosoftBuildVersion is pinned per-TFM to match each SDK's MSBuild; dropping the 8.0/9.0 pins removes that maintenance burden.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions