Skip to content

Give each TFM build its own GitVersion output file - #402

Merged
hahn-kev merged 1 commit into
masterfrom
fix-gitversion-output-race
Oct 2, 2026
Merged

hahn-kev merged 1 commit into
masterfrom
fix-gitversion-output-race

Conversation

@hahn-kev

@hahn-kev hahn-kev commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

Prevents build failures on a race between 2 TFM builds writing the same file.


AI summary

CI intermittently failed building src/LibChorus/LibChorus.csproj for net462 with:

error MSB4044: The "GetAssemblyVersion" task was not given a value for the required parameter "NuGetVersion". [src/LibChorus/LibChorus.csproj::TargetFramework=net462]

(seen in https://github.com/sillsdev/chorus/actions/runs/36810778313, while the netstandard2.0 build of the same project succeeded).

Cause. GitVersion.MsBuild 5.10.3 runs gitversion.exe in every inner build (RunGitVersion is hooked before GetAssemblyVersion/CoreCompile) and writes the result to GitVersionOutputFile, which defaults to obj/gitversion.json. That file is shared by all TFMs of a project, and the inner builds run in parallel. If one build's GetVersion reads the file while another build's gitversion has truncated it for rewriting, GetVersion succeeds silently with empty outputs, Version ends up empty, and the SDK's GetAssemblyVersion fails. Emptying obj/gitversion.json and building net462 with gitversion stubbed out reproduces the exact error, with no GetVersion warning (matching the CI log). This affects every multi-targeted project: LibChorus, ChorusMerge, ChorusMerge.Tests and LibChorus.Tests. It's the same class of race as the mercurial.ini one fixed in #401.

Fix. In Directory.Build.props, inner builds set GitVersionOutputFile to obj/gitversion.$(TargetFramework).json. The outer build (no TargetFramework, used by pack) keeps obj/gitversion.json. It has to be in .props, because GitVersion's props bake the path into the command line at evaluation time. It uses a literal relative obj/ because BaseIntermediateOutputPath isn't set yet at that point and the path goes unquoted into the gitversion command line.

Test plan

  • Reproduced MSB4044 with an empty obj/gitversion.json before the fix
  • dotnet msbuild -getProperty shows a distinct output file per TFM, with the outer build unchanged
  • 5 clean parallel dotnet build Chorus.sln -m -c Release runs: 0 errors
  • Assembly/file/product versions of LibChorus (net462, netstandard2.0, net8.0) and ChorusMerge, and all nupkg versions, are the same as before the fix
  • After a temporary commit, the per-TFM json files, built assemblies and packed nuspec all picked up the new SHA and commit count, so the version still comes from git

🤖 Generated with Claude Code


This change is Reviewable

GitVersion.MsBuild runs gitversion in every inner build and writes
obj/gitversion.json by default, so the parallel inner builds of a
multi-targeted project (LibChorus, ChorusMerge, and their tests) share
one file. If one build reads it while another is rewriting it, GetVersion
silently gets empty values and GetAssemblyVersion fails with MSB4044
("not given a value for the required parameter NuGetVersion").

Write obj/gitversion.$(TargetFramework).json in inner builds instead. The
outer build keeps obj/gitversion.json.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@hahn-kev
hahn-kev requested a review from rmunn October 1, 2026 03:43
@github-actions

github-actions Bot commented Oct 1, 2026

Copy link
Copy Markdown

Test Results

       8 files  ±0     346 suites  ±0   1h 14m 40s ⏱️ + 1m 26s
1 031 tests ±0     975 ✔️ ±0    56 💤 ±0  0 ❌ ±0 
3 266 runs  ±0  3 143 ✔️ ±0  123 💤 ±0  0 ❌ ±0 

Results for commit af4c4fa. ± Comparison against base commit 116b10b.

@hahn-kev
hahn-kev merged commit beacc55 into master Oct 2, 2026
7 checks passed
@hahn-kev
hahn-kev deleted the fix-gitversion-output-race branch October 2, 2026 08:22
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.

2 participants