Skip to content

Keep test runs out of the machine's NuGet global-packages folder - #15

Merged
vfofanov merged 3 commits into
mainfrom
fix/test-nuget-isolation
Oct 6, 2026
Merged

vfofanov merged 3 commits into
mainfrom
fix/test-nuget-isolation

Conversation

@vfofanov

@vfofanov vfofanov commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Test runs could write a package they build into the machine's global-packages folder, where every other build on the machine resolves it instead of the published one. Nothing does so today (measured below); the coming tests that build real kit packages would.

  • tests/run.sh and the new tests/manager.sh set NUGET_PACKAGES to a folder under dist/ for the run and remove it at the end, unless the caller set one.
  • The machine's folder is a read-only fallback (NUGET_FALLBACK_PACKAGES), so third-party packages are not downloaded again; --no-nuget-fallback restores everything into the run's folder.
  • Guard: each run packs a probe package, restores it, and fails if any package it built is in the machine's folder. The same check runs against a copy that leaks, and must report it.
  • CI: the manager job runs tests/manager.sh; the self-test job gets the isolation from tests/run.sh.
  • CONTRIBUTING.md and the changelog describe it.
Evidence

What a run writes to the machine's folder today (main at 3c8a823, id/version list of the folder before and after sh tests/run.sh, then build, test, pack and dotnet tool install --tool-path of the manager): no locally built package and no new third-party package. Packs go to dist/, and a tool installed into a tool path keeps its own store.

Fallback folder is read-only (.NET SDK 10.0.401, a scratch project, NUGET_PACKAGES = a scratch folder, NUGET_FALLBACK_PACKAGES = the machine's folder):

  • a package the machine's folder holds is used from there: the scratch folder has no copy, and the file list of its directory (names, sizes, mtimes) is identical before and after;
  • a package held nowhere and a locally packed one land only in the scratch folder; the machine's id/version list is identical before and after;
  • a package a fallback folder already holds at the same version is served from it, which is why the guard fails on any package of the run found in the machine's folder.

Guard goes red: in a copy whose nuget.config makes a scratch directory the machine's folder, with the isolation removed, tests/run.sh and tests/manager.sh each exit 1 naming dragoant.fixture.cacheprobe <version>; with the isolation kept, tests/manager.sh passes and the scratch directory stays empty.

Run time on CI, this branch against the last three runs of main (one sample of this branch):

Job main This branch
Self-test, Ubuntu 2m 22s to 2m 40s 3m 25s
Self-test, Windows 3m 29s to 3m 41s 3m 06s
Manager, Ubuntu 32s to 39s 41s
Manager, Windows 69s to 77s 83s

Locally the self-test took 38m 13s before and 37m 29s after on a Windows machine that was busy with other work the whole time, so the fallback costs nothing measurable there; the cost of --no-nuget-fallback could not be separated from that load. The added checks pack one small project and restore it twice.

- tests/run.sh and the new tests/manager.sh set NUGET_PACKAGES to a
  folder under dist/ for the run and remove it at the end, unless the
  caller set one; the machine's folder is a read-only fallback
- a probe package is packed and restored to show where a restore
  writes, and the check is run against a copy that leaks
@vfofanov
vfofanov marked this pull request as ready for review October 6, 2026 13:30
@vfofanov
vfofanov merged commit 144c5a0 into main Oct 6, 2026
4 checks passed
@vfofanov
vfofanov deleted the fix/test-nuget-isolation branch October 6, 2026 13:32
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