Skip to content

Isolate tests from global git config to prevent gpg-agent/pinentry#531

Merged
wesm merged 2 commits intoroborev-dev:mainfrom
cpcloud:worktree-vast-herding-hennessy
Mar 17, 2026
Merged

Isolate tests from global git config to prevent gpg-agent/pinentry#531
wesm merged 2 commits intoroborev-dev:mainfrom
cpcloud:worktree-vast-herding-hennessy

Conversation

@cpcloud
Copy link
Copy Markdown
Contributor

@cpcloud cpcloud commented Mar 17, 2026

Summary

  • Add GIT_CONFIG_GLOBAL=/dev/null, GIT_CONFIG_NOSYSTEM=1, and GIT_TERMINAL_PROMPT=0 to testenv.RunIsolatedMain() so tests never read global/system git config or prompt for input — prevents commit.gpgsign=true from triggering gpg-agent/pinentry during test commits
  • Add TestMain calling RunIsolatedMain() to internal/git, internal/prompt, and internal/worktree packages that create git commits in tests but were missing it
  • Fix TestEnsureAbsoluteHooksPath subtest that simulates global config by explicitly setting GIT_CONFIG_GLOBAL to its fake gitconfig file (since /dev/null override would otherwise shadow it)

🤖 Generated with Claude Code

Add GIT_CONFIG_GLOBAL=/dev/null, GIT_CONFIG_NOSYSTEM=1, and
GIT_TERMINAL_PROMPT=0 to RunIsolatedMain() so tests never read
the user's global git config or prompt for input. Add TestMain
to internal/git, internal/prompt, and internal/worktree packages
that create git commits in tests but were missing it.

Fix the EnsureAbsoluteHooksPath test that simulates global config
by explicitly setting GIT_CONFIG_GLOBAL to its fake gitconfig file.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@roborev-ci
Copy link
Copy Markdown

roborev-ci bot commented Mar 17, 2026

roborev: Combined Review (1c68142)

Summary: The changes successfully isolate git test environments, but there is one medium severity issue regarding cross-platform compatibility in the test harness.

Medium

  • [internal/testenv/testenv.go:29](/home/roborev/repos/
    roborev/internal/testenv/testenv.go#L29)

    GIT_CONFIG_GLOBAL is hardcoded to /dev/null, which makes the shared test harness Unix-specific. If this test suite is run on Windows or any environment where that path is not valid
    , Git may fail to read the configured global file and the package tests will break before they reach the intended isolation behavior. Suggested fix: create an empty temp file inside tmpDir and point GIT_CONFIG_GLOBAL at that file instead of relying on a platform-specific null device.

Synthesized from 3 reviews (agents: codex, gemini | types: default, security)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@roborev-ci
Copy link
Copy Markdown

roborev-ci bot commented Mar 17, 2026

roborev: Combined Review (02d23ed)

Verdict: Approved

All agents agree the code is clean and no issues were found. The changes successfully harden test isolation around Git without introducing any security or functional regressions.


Synthesized from 3 reviews (agents: codex, gemini | types: default, security)

@wesm wesm merged commit 5b1aec5 into roborev-dev:main Mar 17, 2026
8 checks passed
@cpcloud cpcloud deleted the worktree-vast-herding-hennessy branch March 17, 2026 23:35
wesm pushed a commit that referenced this pull request Mar 18, 2026
## Summary

- **Isolate agent, config, and review tests from global git config** —
extends #531 to three more packages. Adds `TestMain` calling
`testenv.RunIsolatedMain()` so `git` operations in tests never trigger
the host's `gpg-agent`/`pinentry` (which can add 1-2s per invocation on
machines with GPG signing configured).

- **Make worker pool idle sleeps responsive to shutdown** — replaces
`time.Sleep` in the worker idle loop with a `select` on a shutdown
channel, so tests that stop the daemon don't block waiting for the sleep
to finish.

- **Stub `isPROpenFn` in CI poller test harness** — avoids shelling out
to `gh` CLI during tests. Removes a source of ~0.5s latency and flaky
failures when `gh` isn't authenticated.

- **Parallelize daemon subtests** — marks 21 independent daemon tests as
`t.Parallel()`, including `TestIsDaemonAliveLegacyStatusCodes` subtests
and the bulk of the worker/failover/cancellation tests. Drops
`internal/daemon` from ~7.2s to ~4.2s.

- **Tighten `requireNever` timeout** — the invalid-config watcher test
was waiting 500ms for a "never" assertion; 100ms is sufficient and
shaves ~400ms.

- **Fix `configureSubprocess` to always set `Cancel` on `exec.Cmd`** —
when called on a plain `exec.Command` (no context), `cmd.Cancel` is nil,
so the wrapper's `cancel()` call panicked. Now sets a default `Kill`
cancel before wrapping. This is a correctness fix surfaced by the timing
changes below.

- **Speed up agent subprocess tests (8s → 1s)** — two changes:
1. Override `subprocessWaitDelay` from 5s to 50ms in tests that don't
need the production grace period.
2. Add a Go 1.25 ETXTBSY probe guard (`case "$1" in *etxtbsy*) exit 0;;
esac`) to shell-script test fixtures.

### Go 1.25 ETXTBSY probe — why the guard is necessary

Go 1.25 added a built-in [ETXTBSY probe](https://go.dev/cl/528438) to
`os/exec`: every `Cmd.Start()` call forks a child that runs
`execve(path, [path, "--help-probe-etxtbsy"])`. If `execve` succeeds
(file isn't busy), the probe child **actually executes the script** — it
isn't killed, and the parent waits for it to exit before proceeding.

For shell scripts, this means the script runs **twice**: once as the
probe (with `$1 = "--help-probe-etxtbsy"`), and once as the real
invocation. If the script ignores `$1` and does something slow (like
`sleep 5`), the probe child runs the full body, and Go waits for it —
adding the script's entire runtime as invisible overhead to
`Cmd.Start()`.

This was confirmed via `strace -f`: two child PIDs ran the same
`clock_nanosleep(5s)`, one from the probe fork
(`CLONE_VFORK|CLONE_PIDFD`) and one from the real execution. The probe
child was waited on via `waitid(P_PIDFD)`.

The guard pattern — `case "$1" in *etxtbsy*) exit 0;; esac` as the first
line after the shebang — makes the probe child exit immediately. This is
only needed in test fixtures; real agent binaries already handle unknown
flags gracefully.

Further details are documented in `internal/agent/agent_test_helpers.go`
on the `writeTempCommand` function.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.6 <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.

2 participants