Repository navigation
fix(csharp-ci): install dotnet-coverage per job, not into the shared global tools dir - #41
Merged
Merged
Conversation
…global tools dir Every runner slot on a shared self-hosted host runs as one Unix user and shared ~/.dotnet/tools. A job whose pin differed uninstalled the global dotnet-coverage while another slot's dotnet-coverage merge was running, crashing it with a Microsoft.CodeCoverage.Instrumentation FileNotFoundException (exit 134). Install into $RUNNER_TEMP with --tool-path and prepend it to GITHUB_PATH instead.
monsieurleberre
marked this pull request as ready for review
September 28, 2026 23:42
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The
Install dotnet-coveragestep incsharp-ci.yamlinstalled the tool globally withdotnet tool install -g. On a self-hosted host that runs several runner slots as the same Unix user, every slot shares one~/.dotnet/tools. Consumers pin different versions throughMicrosoft.Testing.Extensions.CodeCoverage, and since #31 each job uninstalls and reinstalls the global tool whenever its pin differs from the version already there.This was measured on 2026-09-28 on two slots of one host:
22:12:21.8994Z: a job pinned to 18.11.0 loggeddotnet-coverage 18.11.2 installed, want 18.11.0 — reinstallingand uninstalled 18.11.2.22:12:21.9037Z: another repo'sdotnet-coverage mergestep on a different slot, pinned to 18.11.2, crashed with aMicrosoft.CodeCoverage.InstrumentationFileNotFoundException(exit 134).Consumers currently pin at least four different versions (18.9.0 to 18.11.2), so these overlaps are routine.
Fix
scripts/install-dotnet-coverage.shnow installs the pinned version with--tool-path "$RUNNER_TEMP/dotnet-coverage-<version>"and prepends that directory toGITHUB_PATH.RUNNER_TEMPis private to the runner slot and wiped between jobs, which is the same precedent #33 set for go-ci. Because the global tool is never touched, no job can pull a binary out from under another job.GITHUB_PATHentries go ahead of the runner'sPATH, so a stale globaldotnet-coverageleft in~/.dotnet/toolsis shadowed rather than used. The script fails loud ifRUNNER_TEMPorGITHUB_PATHis unset.This needs no change on the runner host.
Verification
test/install-dotnet-coverage_test.shwas rewritten for the new contract. It checks the job-private tool path, theGITHUB_PATHline, a separate path per pin, an install failure leavingGITHUB_PATHuntouched, and a usage error and missingRUNNER_TEMPmaking no dotnet call.dotnet-coverage --versionresolved to it through the emitted path, and adotnet-coverage merge -f coberturaexited 0. A second run in the same job is idempotent.Rollout
All callers use
csharp-ci.yaml@v2, so the fix reaches them only after a maintainer tags a release (v2.4.2) and movesv2. Nothing has been tagged.