Fail a bare invocation when stdout is not a terminal #4

Merged
benvin merged 10 commits from benvin/fix-invocation-guards into master 2026-09-24 21:14:38 +10:00

10 Commits

Author SHA1 Message Date
unkin-agent d39ca1e3a6 Rewrap the isTerminal comment
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/integration Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
2026-09-22 23:49:34 +10:00
unkin-agent 0860da03c4 Document the untagged hermetic-env helper
ci/woodpecker/pr/build Pipeline was canceled
ci/woodpecker/pr/integration Pipeline was canceled
ci/woodpecker/pr/pre-commit Pipeline was canceled
ci/woodpecker/pr/test Pipeline was canceled
2026-09-22 23:49:06 +10:00
unkin-agent 173a82f29e Pin x/term v0.45.0 and x/sys v0.47.0
Newest pair still declaring go 1.25.0; v0.46.0/v0.48.0 declare
go 1.26.0 and break the golang:1.25 CI images.
2026-09-22 23:48:59 +10:00
unkin-agent ddd93a8b71 Assert the hermetic env replaces the ambient one, not extends it
The shape test passed on `return os.Environ()`; only a Vault-backed
test caught it. Move the helper and its test out from behind the
integration tag and reject any entry outside PATH/HOME/XDG_CONFIG_HOME.
2026-09-22 23:48:59 +10:00
unkin-agent 21990d9297 Pass an explicit empty argv so cobra cannot reach os.Args
A nil argv lets cobra fall back to os.Args[1:], which under
`go test -args foo` turns the bare-invocation cases into
`certmanager foo` and resolves /opt/certmanager/config.yaml. Assert
the bare-invocation error on stderr so the fallback cannot hide.

Puppet gives the child a temp file as fd 1, not a pipe; say so.
2026-09-22 23:48:59 +10:00
unkin-agent b0099991c0 Poison both config legs the hermetic env has to strip
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/integration Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
2026-09-22 23:29:32 +10:00
unkin-agent c6c3f6a092 Pin the invocation gate against every kind of stdout 2026-09-22 23:29:32 +10:00
unkin-agent 30eee88d95 Detect a terminal with an ioctl, not a character-device stat
/dev/null is a character device, and so is the /dev/null the Go runtime
reopens onto a closed fd 1, so a bare invocation printed help and exited
zero for both -- the two shapes a machine caller is most likely to hand
the binary.
2026-09-22 23:29:32 +10:00
unkin-agent 5a7fea56e2 Document the interactive seam in AGENTS.md
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/integration Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
2026-09-22 22:58:52 +10:00
unkin-agent 4ff55f052a Fail a bare invocation when stdout is not a terminal
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/integration Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline failed
Puppet's generate() reads stdout through a pipe with combine: true, so help
text on a zero exit lands in the catalog. Help now requires an interactive
stdout; a piped one exits non-zero with nothing on stdout.

- gate the no-args help path on an isTerminal(stdout) check
- reject an explicitly empty --config instead of resolving it
- ignore a relative XDG_CONFIG_HOME, per the XDG spec
- give the integration subprocess a hermetic HOME/XDG_CONFIG_HOME
- pass []string{} to run(), so cobra cannot fall back to os.Args
2026-09-22 22:50:05 +10:00