Skip to content

fix(tests): unset inherited GIT_DIR/GIT_INDEX_FILE for hermetic fixture tests#614

Merged
joshjhall merged 2 commits into
mainfrom
feature/issue-599
Jun 27, 2026
Merged

fix(tests): unset inherited GIT_DIR/GIT_INDEX_FILE for hermetic fixture tests#614
joshjhall merged 2 commits into
mainfrom
feature/issue-599

Conversation

@joshjhall

Copy link
Copy Markdown
Owner

Summary

tests/framework.sh did not clear inherited git environment variables
(GIT_DIR, GIT_INDEX_FILE, GIT_WORK_TREE, GIT_COMMON_DIR, GIT_PREFIX).
git exports these into hook environments (e.g. lefthook pre-push), so any test
that builds a throwaway git fixture (git init / git worktree add in a
mktemp dir) had its nested git commands hijacked back at the real repo
when run from a hook — fixtures silently failed to build, assertions diverged
from the standalone run, and stray commits could land on the live branch
(surfaced in #587: 6/9 fail + 46 stray init commits).

This clears the five inherited git vars once, centrally, at framework.sh
module scope (before the sub-module source calls), so every current and
future fixture test — and the framework bootstrap itself — is hermetic
regardless of how the suite is invoked (standalone, run_unit_tests.sh, or a
git hook). init_test_framework keeps a belt-and-suspenders re-clear.

Changes

  • tests/framework.sh — unset inherited git env at module scope + re-clear in init_test_framework.
  • tests/unit/claude/test_golem_notify.sh — drop the now-redundant per-test unset from fix(skills): golem-notify.sh records golem-? (issue number lost) when Notification fires outside worktree root #587 (proves the central guard suffices).
  • tests/unit/test_framework_git_hermetic.shnew regression test: exports a bogus GIT_DIR in a clean child shell, runs init_test_framework, and asserts (a) all five vars are cleared and (b) a fixture git init resolves inside the temp dir, never the inherited bogus GIT_DIR.

Acceptance criteria

  • init_test_framework (and module scope) unsets GIT_DIR, GIT_INDEX_FILE, GIT_WORK_TREE, GIT_COMMON_DIR, GIT_PREFIX before any test body runs.
  • test_golem_notify.sh passes 9/9 under env GIT_DIR=... GIT_INDEX_FILE=... with its per-test unset removed.
  • A regression test asserts the framework clears the git env (bogus GIT_DIR → fixture git init still lands in the temp dir).
  • The three existing fixture tests still pass under hook conditions.

Test plan

  • Reproduction from the issue now passes: env GIT_DIR=$(git rev-parse --git-dir) GIT_INDEX_FILE=$(git rev-parse --git-path index) bash tests/unit/claude/test_golem_notify.sh → 9/9.
  • New test_framework_git_hermetic.sh → 2/2, standalone and under a polluted git env.
  • Existing fixture tests (update-versions.sh, test_pre_review_gates.sh, test_patterns_sh.sh) → Failed: 0 under hook env.
  • Full unit suite: 3097 passed, 0 failed, 5 skipped. shellcheck clean; lefthook pre-commit + pre-push green.

Review

Adversarial pre-PR review (5 dimensions + judge + gatekeeper): 0 blocking, 7 deferrable. The genuinely valuable findings were resolved in this PR rather than deferred — module-scope guard placement (closes the bootstrap gap), env-var passing of the framework path (apostrophe-path quoting safety), full command paths for env/bash, and a positive "gitdir inside temp dir" assertion. Two low-confidence findings were assessed as incorrect/low-value and discarded (one claimed outer-shell $tmp expansion that the passing positive assertion disproves; one PATH-narrowing suggestion of marginal value).

Closes #599

…ic fixtures

git exports GIT_DIR/GIT_INDEX_FILE/GIT_WORK_TREE/GIT_COMMON_DIR/GIT_PREFIX into
hook environments (e.g. lefthook pre-push). Fixture-building tests that run
`git init`/`git worktree add` in a mktemp dir had those nested git commands
hijacked back at the real repo when run from a hook — fixtures silently failed
to build, assertions diverged from the standalone run, and stray commits could
land on the live branch (surfaced in #587: 6/9 fail + 46 stray commits).

Unset the five inherited git vars once, centrally, in init_test_framework so
every current and future fixture test is hermetic regardless of how it was
invoked. Remove the now-redundant per-test unset from test_golem_notify.sh
(#587) and add tests/unit/test_framework_git_hermetic.sh, which exports a bogus
GIT_DIR in a child shell and asserts both that the vars are cleared and that a
fixture `git init` lands in the temp dir.

Closes #599
Address pre-PR adversarial review findings:

- Move the inherited git-env unset to framework.sh module scope so the
  framework bootstrap (the sub-module `source` calls) is protected too, not
  just test bodies. init_test_framework keeps a belt-and-suspenders re-clear.
  This also lets test_golem_notify.sh rely on the central guard during its own
  `source framework.sh`, closing the implicit-invariant gap.
- Pass FRAMEWORK_SH through the environment instead of interpolating it into
  the `bash -c` string, and quote the static prefix, so a repo path containing
  a single quote can't break out of the source argument.
- Use full paths for `env`/`bash` in run_in_polluted_env, matching the sibling
  test_golem_notify.sh convention (CLAUDE.md full-paths rule).
- Add a positive assertion that the fixture gitdir resolves inside the temp
  dir, not merely "not the bogus path", closing a third-location gap.
@joshjhall joshjhall merged commit 22aea17 into main Jun 27, 2026
23 checks passed
@joshjhall joshjhall deleted the feature/issue-599 branch June 28, 2026 04:21
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.

test framework: unset inherited GIT_DIR/GIT_INDEX_FILE so fixture tests are hermetic under git hooks

2 participants