Skip to content

testidentity: no test identity reaches a commit, and no test's git the checkout - #104

Merged
aledbf merged 1 commit into
mainfrom
test-identity
Nov 13, 2026
Merged

aledbf merged 1 commit into
mainfrom
test-identity

Conversation

@aledbf

@aledbf aledbf commented Nov 13, 2026

Copy link
Copy Markdown
Member

Follow-up to spin-stack/spin#1196. Twice a test in spin wrote user.name "Ana Lima" / ana@corp.example into a shared .git/config, and every worktree's commits carried it to GitHub. This makes that class impossible here and gives every repository the check.

Tests here cannot reach the checkout's git

  • internal/gittest: Command/Run run git only under the temporary directory, refuse -C/--git-dir/--work-tree, stop git's search at the temp root and the checkout (GIT_CEILING_DIRECTORIES), read no global or system config, drop every inherited GIT_* (a hook's GIT_DIR), and commit as gittest@go-tools.invalid. Fence() does the same for a package whose own code runs git, from its TestMain.
  • Every test that ran git now goes through it. That includes internal/mutate's git config user.email test@example.com: it ran in a fresh temp repo, so it was safe until a hook's GIT_DIR or a lost init sent it to the checkout. Ten packages whose code runs git now fence their tests. The site's CI example is copied into a repo of its own instead of being read in place.
  • internal/gitexec: its test walks this module and fails on any test file that execs git itself, and on any package whose code runs git and whose tests don't fence it (spin's gitexec, ported).

cmd/testidentity: the authors gate, for every repository

  • Checks every commit in BASE..HEAD (-base origin/main). It fails when a raw author or committer address is at a reserved domain (RFC 2606/6761 TLDs, .local, .internal, example.{com,net,org}, home.arpa), has no dot, or appears in the tree's tests and fixtures (git ls-files: Go, JS/TS, Terraform tests, and test(s)/, testdata/, fixtures/, e2e/, mocks/ dirs).
  • GitHub's noreply, bot and noreply@github.com addresses pass by rule.
  • -allow is a ratchet: every line needs a reason, and a line whose address no longer looks like a test's fails.
  • On a finding it prints the steps to fix it. It exits 2 when it can't run the check, for example when the base isn't in the clone.
  • It ships in the release with the other commands, so under go tool task it is on PATH. task lint runs it on this repo. There is a site page.

Checked: task test, task lint, task mutate (92 refused, 0 survived), task site. The tests plant each failure: unfenced git, a TMPDIR inside the checkout, a hook's GIT_DIR, a commit by a test author or committer, a fixture address, a stale allow line, and a missing base.

🤖 Generated with Claude Code

…e checkout

Twice a test in spin wrote its author into the checkout's .git/config and every worktree
committed as it, to GitHub. Two halves, the same as spin#1196's:

- internal/gittest is how a test here runs git: under the temporary directory, with git's
  search stopped at the checkout and the temporary directory, no inherited GIT_ variable, no
  global or system configuration, and an author at go-tools.invalid. A package whose own code
  runs git fences its tests in TestMain. internal/gitexec's test fails on a test that runs git
  another way, and on such a package without the fence. mutate's TestTheLinesAChange... ran
  `git config user.email` in a fresh temp repository - safe until a hook's GIT_DIR or a lost
  init sends it to the checkout - and goes through gittest like the rest.
- cmd/testidentity, released with the other commands so every repository runs it under
  `go tool task`: a commit since the base whose author or committer is at a reserved domain,
  has no dot, or is spelled in the tree's tests and fixtures, fails, with what to do. GitHub's
  noreply and bot addresses are real by rule; -allow is a ratchet with reasons. task lint runs
  it on this repository.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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