Skip to content

perf: disable GitVersion MSBuild task globally#5266

Merged
thomhurst merged 1 commit intomainfrom
perf/disable-gitversion-msbuild-task
Mar 27, 2026
Merged

perf: disable GitVersion MSBuild task globally#5266
thomhurst merged 1 commit intomainfrom
perf/disable-gitversion-msbuild-task

Conversation

@thomhurst
Copy link
Copy Markdown
Owner

Summary

  • Disable GitVersion MSBuild task by default in Directory.Build.props — eliminates 153+ dotnet-gitversion process spawns per build. CI already computes the version once via gittools/actions/gitversion/execute and passes properties explicitly, making the per-project MSBuild task redundant.
  • Skip CleanSourceGeneratedViewer in CI — the target was running every build with no Inputs/Outputs, deleting and recreating source-gen viewer files unnecessarily. Now conditioned on ContinuousIntegrationBuild != true and directory existence.
  • Remove redundant -p:DisableGitVersionTask=true from CI workflow — no longer needed since it's the default.
  • Fix unquoted MSBuild condition expressions (AP-02) in Directory.Build.props and TUnit.Templates/content/Directory.Build.props.

Performance Impact

Metric Before After
Incremental no-op ~30s ~4s
Full build 5m 27s 4m 20s

Test plan

  • Full solution build succeeds (dotnet build TUnit.CI.slnx)
  • Incremental build correctly skips all targets (~4s)
  • CI workflow builds and passes (version properties still passed explicitly)

…terns

Disable the GitVersion MSBuild task by default in Directory.Build.props,
eliminating 153+ process spawns per build. CI already computes the version
once and passes properties explicitly, so the per-project task was redundant.

Also:
- Skip CleanSourceGeneratedViewer in CI and when directory doesn't exist
- Remove redundant -p:DisableGitVersionTask=true from CI workflow
- Fix unquoted MSBuild condition expressions (AP-02)

Incremental no-op build: ~30s → ~4s
Full build: 5m27s → 4m20s
Copy link
Copy Markdown
Contributor

@claude claude bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This is a well-targeted, low-risk performance PR. The changes are clearly motivated and the implementation is sound. A few observations:


DisableGitVersionTask in Directory.Build.props

Good move. GenerateGitVersionInformation=false was already set, meaning no class was being generated — but the GitVersion MSBuild task was still spawning a process. Setting DisableGitVersionTask=true globally prevents that process from running entirely.

The 153+ per-TFM invocation problem is real in large solutions that multi-target (net8/net9/net10), and the fix here is correct: CI already computes the version once via gittools/actions/gitversion/execute and injects the properties explicitly via -p:, so the per-project task serves no purpose.

One thing worth documenting (even if just as a comment above the property): local developer builds will no longer have GitVersion-computed version properties unless they pass them explicitly. Since GenerateGitVersionInformation was already false, the generated GitVersionInformation class wasn't available anyway, so this mainly matters for anyone trying to do local NuGet pack testing. It's probably fine for this repo, but a comment clarifying the local-dev trade-off would help future maintainers avoid confusion.


CleanSourceGeneratedViewer target conditions (TestProject.props)

The two new conditions are both correct:

  • '$(ContinuousIntegrationBuild)' != 'true' — CI doesn't need the SourceGeneratedViewer at all, so skipping the delete-and-recreate cycle there is the right call.
  • Exists('$(ProjectDir)SourceGeneratedViewer') — avoids a no-op ItemGroup+Delete on first build before the directory exists.

The <Message> removal is also a good cleanup — unconditional MSBuild log noise hurts incremental-build usability.

One minor architectural note: the target still lacks Inputs/Outputs for proper MSBuild incremental tracking on local builds, meaning it runs before every local build when the directory exists. For a fast directory-clean target this is probably acceptable, but if the viewer directory ever grows large (many TFMs × many source generators), adding an Inputs/Outputs guard would be the idiomatic MSBuild solution.


✅ MSBuild condition quoting fixes

The $(MSBuildProjectName) == 'TUnit.Pipeline''$(MSBuildProjectName)' == 'TUnit.Pipeline' fixes are correct. Unquoted property references in MSBuild Condition expressions can silently evaluate unexpectedly (e.g., when the property is empty, the expression becomes == 'TUnit.Pipeline' which may parse differently across MSBuild versions). The quoted form is the canonical, safe syntax.


✅ CI workflow cleanup

Removing the now-redundant -p:DisableGitVersionTask=true overrides from both the Build and Publish AOT steps is correct housekeeping. The root Directory.Build.props now owns this setting globally.


Summary

The performance claims (~30s → ~4s no-op local, 5m27s → 4m20s CI) are plausible given the described root cause (153+ subprocess invocations). The changes are minimal, focused, and correct. The only suggestion I'd offer is adding a brief developer-facing comment near DisableGitVersionTask to explain the local-dev implication, which would make the intent clear to anyone who encounters a $(Version) that resolves empty in a local build.

Approved.

@thomhurst thomhurst enabled auto-merge (squash) March 27, 2026 13:07
@thomhurst thomhurst merged commit a38f5ef into main Mar 27, 2026
14 of 15 checks passed
@thomhurst thomhurst deleted the perf/disable-gitversion-msbuild-task branch March 27, 2026 13:35
thomhurst added a commit that referenced this pull request Mar 28, 2026
DisableGitVersionTask=true was added in #5266 but PackTUnitFilesModule
was not updated to pass version properties explicitly. This caused
dotnet pack to rebuild assemblies with default AssemblyVersion (1.0.0.0),
creating strong-name version mismatches at runtime in consumers
(FileNotFoundException for TUnit.Core).
thomhurst added a commit that referenced this pull request Mar 28, 2026
DisableGitVersionTask=true was added in #5266 but PackTUnitFilesModule
was not updated to pass version properties explicitly. This caused
dotnet pack to rebuild assemblies with default AssemblyVersion (1.0.0.0),
creating strong-name version mismatches at runtime in consumers
(FileNotFoundException for TUnit.Core).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant