Skip to content

fix(ci): isolate git from the ambient environment so -C is authoritative (#13948) - #13949

Merged
mrveiss merged 3 commits into
Dev_new_guifrom
issue-13948
Aug 11, 2026
Merged

mrveiss merged 3 commits into
Dev_new_guifrom
issue-13948

Conversation

@mrveiss

@mrveiss mrveiss commented Aug 10, 2026 •

Copy link
Copy Markdown
Owner

Correction: this PR originally said Closes #13948. That number belongs to an unrelated open issue — the filing command was malformed so the intended issue was never created. The correct issue is #13983; #13948 has been reopened and is untouched.

Closes #13983

Thinking Path

python-suite shard 2/12 is red on Dev_new_gui — failing on every PR that runs it, including #13902, a dependabot bump touching nothing related.

The message pointed at the wrong thing:

error: invalid object 100644 dae199ae... for 'solo_12.py'
error: Error building trees

That reads as repository corruption inside a test about co-change coupling. The popen-gw1 in the tmpdir path is the actual tell — it only happens with parallel workers, which is why it looked intermittent.

Git treats GIT_INDEX_FILE as higher precedence than -C. With one exported into the job, every xdist worker stages into the same index while committing in its own tmpdir repo, so a worker writes a tree whose blobs live in another worker's object store.

Reproduced exactly before writing any fix:

$ GIT_INDEX_FILE=/tmp/shared-index pytest co_change_test.py -n 4
E   stderr: error: invalid object 100644 13ceda20... for 'busy.py'
E   error: Error building trees

Without -n 4, or without the variable, it passes — which is why the failure message alone never reproduced it.

What Changed

co_change_test.py — _git and _git_init run under _hermetic_git_env(): the ambient environment minus the variables that outrank -C, plus GIT_CONFIG_GLOBAL/SYSTEM=/dev/null and an explicit identity, so the fixture no longer depends on the runner having git configured.

code_evolution_miner._run_git — the same isolation, for a quieter and worse problem. With GIT_DIR exported, the crawler reads that repository instead of the one passed to -C and returns a perfectly plausible history for the wrong tree: no error, no empty result, just an answer about something else. Confirmed by the suite switching from failing to hanging once GIT_DIR pointed at the main checkout — it was walking the real repo's history.

Variables are named explicitly rather than stripping GIT_* wholesale: GIT_AUTHOR_* and GIT_SSH_COMMAND are legitimate and removing them would break unrelated callers.

Verification

Against the reproduction and the case that must keep passing — not just a re-run:

case before after
GIT_INDEX_FILE + -n 4 (the CI failure) invalid object / Error building trees 23 passed
plain run (must not become a skip) 23 passed 25 passed
GIT_DIR at the main checkout timed out at 100s 25 passed in 9s

3 mutations applied, 3 killed:

mutation result
env=_git_env() removed from _run_git 1 failed
GIT_DIR dropped from the strip list 2 failed
test-side hermetic env removed 4 failed, 13 errors — the original CI failure, reproduced

The new test_the_crawler_reads_the_repo_it_was_given_not_the_ambient_one builds a second repo containing decoy.py, points GIT_DIR at it, and asserts the crawler still reports schema.py and never decoy.py — a not-crashing assertion would have passed against the bug.

Note

Per #13162 the Python suite is not a required check, so this was red on the base without blocking any merge. That is the reason it survived.

Model Used

claude-opus-5[1m]

…ive (#13948)

python-suite shard 2/12 is red on Dev_new_gui, failing on every PR that runs
it — seen on #13902, a dependabot bump touching nothing related.

Git treats GIT_INDEX_FILE as higher precedence than -C, so with one exported
into the job every xdist worker stages into the SAME index while committing in
its OWN tmpdir repo. A worker then writes a tree whose blobs live in another
worker's object store and git reports:

    error: invalid object 100644 dae199ae... for 'solo_12.py'
    error: Error building trees

which reads as repository corruption in a test about co-change coupling. The
popen-gw1 in the path is the tell: it only happens with parallel workers, which
is why it looked intermittent.

Reproduced exactly before fixing:
    GIT_INDEX_FILE=/tmp/shared-index pytest co_change_test.py -n 4
Without -n 4, or without the variable, it passes — which is why the failure
message alone never reproduced it.

GitHistoryCrawler._run_git had the same exposure and a worse failure mode: with
GIT_DIR exported it reads THAT repository instead of the one passed to -C and
returns a plausible history for the wrong tree — no error, no empty result,
just an answer about something else. Confirmed by the suite switching from
failing to HANGING when GIT_DIR pointed at the main checkout.

Variables are named explicitly rather than stripping GIT_* wholesale, because
GIT_AUTHOR_* and GIT_SSH_COMMAND are legitimate and removing them would break
unrelated callers.

Verified against the reproduction and against the case that must keep passing:
reproduction now green, plain run green, GIT_DIR case 9s instead of a timeout.
3 mutations killed — production env isolation removed, GIT_DIR dropped from the
strip list, and the test-side isolation removed (which reproduces the original
CI failure: 4 failed, 13 errors).
@github-actions

Copy link
Copy Markdown
Contributor

✅ SSOT Configuration Compliance: Passing

🎉 No hardcoded values detected that have SSOT config equivalents!

Applied Black, isort, and autoflake to match code-quality checks.
Triggered by workflow auto-fix-formatting.yml.
@mrveiss
mrveiss merged commit 25e776b into Dev_new_gui Aug 11, 2026
62 checks passed
@mrveiss
mrveiss deleted the issue-13948 branch August 11, 2026 07:10
mrveiss added a commit that referenced this pull request Aug 11, 2026
…3983) (#13987)

* chore: claim worktree for #13983

* docs(code-intelligence): correct stale issue references to #13983 (#13983)

#13949 was written against issue number #13948, which belongs to an unrelated
open issue (a distillation-cursor DST bug). The filing command was malformed —
'gh issue create --json number' is not a valid flag combination, so it errored
before creating anything and the '||' fallback returned the newest EXISTING
issue number instead.

That wrong number then reached the PR body, five source comments, and a test
fixture directory name. #13948 has been reopened and is untouched; the real
issue is #13983, filed after the fact with the full diagnosis.

Comments and identifiers only — no behaviour change. The suite still passes.
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