Repository navigation
tests/test_lane_worktrees.py: test_yes_is_refused_for_a_lane_live_elsewhere_or_unread flakes when git packs projects/repoA's objects between its two snapshots #231
Description
What failed
tests/test_lane_worktrees.py::test_yes_is_refused_for_a_lane_live_elsewhere_or_unread[none-binding1-could not be read]
This failed in CI run 38465762981, attempt 1, Linux tests job (head fab2cbc, PR #214, git 2.55.0 on the runner): https://github.com/opensoft/openRepoTools/actions/runs/38465762981/job/115532049111. The job ended 1 failed, 1429 passed, 9 skipped in 3065.66s.
Attempt 2 of the same run passed, with no code change: 1430 passed, 9 skipped in 2482.85s, https://github.com/opensoft/openRepoTools/actions/runs/38465762981/job/117498706925.
The failing assertion is the case's "a refused --yes changes nothing" check (tests/test_lane_worktrees.py:636):
> assert snapshot(estate.root, skip=skip) == before
E AssertionError: assert {'config': (1...d411d4'), ...} == {'config': (1...d411d4'), ...}
E Omitting 150 identical items, use -vv to show
E Left contains 6 more items:
E {'projects/repoA/.git/info/refs': …,
E 'projects/repoA/.git/objects/info/packs': …,
E 'projects/repoA/.git/objects/pack/multi-pack-index': …,
E 'projects/repoA/.git/objects/pack/pack-b73630ba….idx': …,
E 'projects/repoA/.git/objects/pack/pack-b73630ba….pack': …,
E 'projects/repoA/.git/objects/pack/pack-b73630ba….rev': …}
E Right contains 17 more items:
E {'projects/repoA/.git/objects/17': …,
E 'projects/repoA/.git/objects/17/b8037e56…': …,
E 'projects/repoA/.git/objects/1f/096e9c…': …,
E 'projects/repoA/.git/objects/bitmap-ref-tips_bnYr5X': …,
E 'projects/repoA/.git/objects/cf/f5543…': …, …}
Analysis
The test races git's own object packing. Nothing in the case wrote those files.
snapshot()(tests/test_lane_worktrees.py:350) hashes every path under the estate, including each repository's.git/objects. So it compares object STORAGE LAYOUT, not repository content.- Between the
beforesnapshot and the one after the refused--yes, git consolidatedprojects/repoA's loose objects into a pack. The before side has loose objects and abitmap-ref-tips_*temp file. The after side has a pack, amulti-pack-index, and theinfo/refsandobjects/info/packsthatupdate-server-infowrites. That is the signature of an automaticgit repack(--write-midxwith bitmaps), not of anythinglane-worktreesdoes. Its source has no repack, gc or maintenance call, only agit fetch --pruneon a probe (lane-worktrees:2394). - The fixture isolates system config (
GIT_CONFIG_NOSYSTEM=1,:161) but not gc or maintenance. git's automatic maintenance runs after commands such ascommitandfetch, and by default it DETACHES and finishes in the background. So a repack started by the test's ownestate.commit(…), or by a command the sweep runs, can land at any moment. I did not identify which command started it. It passed on re-run, so it is timing, not logic. - The fake
lanes-edit.shis not involved. This case'sEstatefixture puts a Python stub onPATHand pointsLANES_EDITat it (:141,:157).
Suggested fix (either is enough; both is belt and braces)
- Isolate the fixture's repositories from automatic maintenance, as it already isolates system config. In the
Estateenvironment, setGIT_CONFIG_COUNT/GIT_CONFIG_KEY_n/GIT_CONFIG_VALUE_nforgc.auto=0,maintenance.auto=falseandgc.autoDetach=false, or pointGIT_CONFIG_GLOBALat a sandbox file carrying them. Then no repack can start, detached or not. - Compare content, not layout. Have
snapshot()skip.git/objects/**,.git/info/refsand.git/objects/info/packs, and compare each repository's object SET instead (git cat-file --batch-all-objects --batch-check) together with its refs. A repack then changes nothing the test cares about, while a real write still fails it.
The other snapshot(...) == before cases in this file (:568, :753, :816) have the same exposure.
Not related to #214
PR #214 (lanes-edit.sh commit_push) touches neither lane-worktrees nor tests/test_lane_worktrees.py, and this case never runs the real lanes-edit.sh.
Found by lane openRepoTools-4 while working on #214. Not claimed.
🤖 Generated with Claude Code
Activity