{{ message }}
Conversation
`IrisRelease.merge_back` writes a progress file for the *next* patch,
named after that patch rather than date-stamped like every other
`nothing` progress file:
next_patch_stem = self._get_file_stem().with_stem(next_patch_str)
`nothing.Progress._get_file_stem` resolves `.nothing/` against
`Path().cwd()`, which every `pytest-xdist` worker shares. Two tests
reach that code with the same version -- `TestMergeBack::test_branches`
in its `more_patches` parametrisation, and `test_next_patch_file` --
so both resolve to the one `.nothing/v1_1_1.json`.
That is a race, not a conflict. `NextPatch(...)` writes the JSON
non-atomically and then verifies by reloading it, and its logger opens
the sibling `.log` with `mode="w"`. `test_next_patch_file` loads the
same path back and asserts on its contents. With no `--dist` setting
in `pyproject.toml`, xdist schedules dynamically, so whether the two
land on the same worker varies run to run: the observed `py3.14` failure
on SciTools#7276 reproduced on no other job, and the identical commit passed on
re-run.
Give each test its own working directory. An autouse fixture is the
right scope because `_get_file_stem` runs during `__post_init__`, so
every construction of `IrisRelease` is exposed, not just the two tests
that collide today. All three `subprocess` calls in
`release_do_nothing.py` are the git helpers already mocked by autouse
fixtures, and every other path it builds is anchored to `Path(__file__)`,
so moving the working directory reaches nothing else.
This also stops the suite writing `.nothing/` into the repository as a
side effect -- the reason `**/.nothing` sits in `.gitignore`.
The race cannot be reproduced on demand, so the accompanying test
asserts the isolation that prevents it instead of the failure itself.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Member
Author
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.

🤖 Agentic pull request
This was written by Claude (Opus 5), driven by @bjlittle. The commit carries a
Co-Authored-Bytrailer. Please review it as you would any other contribution.Found while investigating the
tests (py3.14)failure on #7276, which wasunrelated to that pull request.
The failure
tools/test_release_do_nothing.py::TestMergeBack::test_next_patch_filefailedon one job and no other. Re-running the identical commit passed. That pattern is
the diagnosis: it is a race between tests, not a bug in the code under test.
What races
IrisRelease.merge_backwrites a progress file for the next patch. Unlikeevery other
nothingprogress file, it is named after that patch instead ofbeing date-stamped —
tools/release_do_nothing.py:1292:nothing.Progress._get_file_stemresolves.nothing/againstPath().cwd(),which every
pytest-xdistworker shares. So the directory is the only thingdistinguishing one test's progress file from another's, and it does not vary.
Two tests reach that line with the same version, and so with the same path,
.nothing/v1_1_1.json:TestMergeBack::test_branches, in itsmore_patchesparametrisationTestMergeBack::test_next_patch_fileBoth set
git_tag = "v1.0.1"andpatch_min_max_tag = ("v1.0.1", "v1.2.1"),which makes the next patch
v1.1.1in each case.It is a race rather than a plain clash because the writes are not atomic and the
reads are not guarded:
NextPatch(...)writes the JSON withwrite_textand then verifies it byloading it straight back.
.logwithmode="w", truncating it.test_next_patch_fileloads the same path and asserts on its contents.pyproject.tomlsets no--dist, so xdist uses dynamic scheduling. Whetherthose two tests land on the same worker varies from run to run, which is exactly
the intermittency observed.
The fix
A module-level autouse fixture giving each test its own working directory.
Autouse is the right scope rather than patching the two colliding tests:
_get_file_stemruns during__post_init__, so every construction ofIrisReleaseis exposed to the shared directory, not just today's twooffenders.
Moving the working directory is safe here. All three
subprocesscalls inrelease_do_nothing.pyare the git helpers (_git_remote_v,_git_remote_get_url,_git_ls_remote_tags), each already mocked by an autousefixture; every other path the module builds is anchored to
Path(__file__).It also stops the suite writing
.nothing/into the working copy as a sideeffect — which is why
**/.nothingis in.gitignore(.gitignore:85). Onmain,pytest toolsleaves.nothing/v1_1_1.jsonandv1_1_1.login therepository root. With this change it leaves nothing behind.
On testing a race
The failure is scheduling-dependent and cannot be reproduced on demand, so
test_progress_files_are_isolatedasserts the isolation that prevents it ratherthan the failure itself.
It is a real regression test: with the fixture body removed it fails, and names
the repository root in the message.
Testing
pytest toolsgives122 passed, 1 skipped, against121 passed, 1 skippedonmain— the one addition is the new test. Passes both serially and under-n auto, and leaves no.nothing/in the repository.Note that
pytest toolsneeds thenothingpackage, which is installed only bynoxfile.pyand appears in no requirements or lock file. That is #7277, raisedseparately for the core developers to rule on; it is an observation, not a
blocker for this.
Why this targets
mainThis is a repository-wide CI fix, not part of the merge/concatenate programme
that the
greenfieldfeature branch carries.greenfieldneeds it too — it inherits the same test module and the samefailure. It should pick it up by mergeback from
main, not a cherry-pick,so the branch keeps a single ancestry and does not carry a duplicate commit that
would have to be resolved later.
greenfielddescends frommain, so the mergeis clean. @bjlittle and I will raise that mergeback once this lands.