fix: headless credential prompts refuse loudly, naming their variable #43
Labels
No labels
attention
blocked
blocker:ci-red
blocker:conflict
blocker:drill-pending
blocker:unrequested
bug
claimed
documentation
enhancement
epic
merge-next
needs-ruling
needs-triage
offsite
post-merge
ready
release
scope:bootstrap
scope:coolify
scope:db
scope:docs
scope:drill
scope:installer
scope:labels
scope:platform
scope:runner
scope:users
stale
state:addressing
state:bots-reviewing
state:building
state:needs-human
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: heavy-duty/rig#43
Loading…
Reference in a new issue
No description provided.
Delete branch "fix/silent-prompts"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Fixes #42.
What
The interactive credential prompts —
TS_AUTHKEY(bootstrap),RUNNER_TOKEN(runner install),RUNNER_REMOVE_TOKEN(runner remove), and both tokens inrunner repoint— were bareread -rsp. With stdin not a tty (CI,box exec, any script),readexits non-zero,set -euo pipefailends the run, and nothing is printed: the drill measuredrig runner removeexiting 1 in total silence, and a guest bootstrap whose log just stops aftersystem hostname already ….How
Each prompt now:
dienaming the exact variable that unblocks an unattended run (runner remove/repointalso name--local), matching how every other refusal in rig behaves (db.sh:152already held this line);readitself with|| die, so EOF at a real prompt (Ctrl-D) also dies with a last word instead of ridingset -einto silence.Tests
read -rspmay exist undercommands/(expectsgrepexit 1). This is the check that caughtrunner repoint's two prompts, which the issue had not counted — it fails on any future prompt added without the cure.bash test/cli.sh: 325 passed, 0 failed ·bash test/release.sh: 41 passed, 0 failed · shellcheck clean.🤖 Generated with Claude Code
✅ Reviewed — I agree with all of this, no concerns.
The two-part cure is right: refuse first with
[ -t 0 ] || dienaming the exact variable that unblocks an unattended run (and--localwhere it applies), then|| die-guard thereadso EOF at a real tty also gets a last word instead of ridingset -einto silence. Every prompt gets the treatment, and the env-var override still skips the prompt so unattended runs with the var set work unchanged. The test design is the strong part — three per-guard grep checks (behind the root check the harness can't cross), plus theread -rsp[^|]*$sweep that expectsgrepexit 1, which is exactly what caughtrunner repoint's two prompts the issue hadn't counted and will catch any future bare prompt added without the cure. Clean.— automated review by
claude-bot-andresmgsl· heavy-duty-review-botApprove. The fix matches the drill-measured failure exactly, covers all five prompt sites (two more than #42 counted), the named variables are spelled correctly against what each script reads, refusals go to stderr with exit 1 via each script's
die, and[ -t 0 ]is reliable here becausebin/rigdispatches withexecso stdin reaches the command untouched. Both suites pass (325 + 41). Notes, none blocking:bootstrap.sh:406,runner-install.sh:126,runner-remove.sh:77,runner-repoint.sh:134,144— each names the variable it actually reads, remove/repoint also name--local, and everyreadcarries the|| dieEOF guard.printf '%s\n' "$TOK" | rig runner install) used to work and is now refused. Undocumented path and the error names the fix, so fine — but it's real.test/cli.sh:483sweep only matches the literalread -rspand only undercommands/; a futureread -s -por a prompt inbin/rigescapes it. Considerread .*-por similar.runner-repoint.shhas no per-guard grep test (only the sweep, which proves the||guard, not the tty refusal). Agrep -casserting 2 hits in repoint would close it.bin/rig:234read -r replyinuninstall_confirmstill dies silently on Ctrl-D at a real tty underset -e(headless is guarded at 228). CHANGELOG's "now all of rig does" slightly overclaims — fair game for a follow-up.— automated review by
claude-bot-andresmgsl· heavy-duty-review-botVerdict: Approve — I agree with this as-is.
Why
read -rspunderset -ewith non-tty stdin exits 1 with no last word. The cure is two-part and consistent withdb.sh: refuse first ([ -t 0 ] || die …) naming the variable that unblocks an unattended run, and|| dieon thereadso EOF on a real tty is equally loud.TS_AUTHKEY(bootstrap),RUNNER_TOKEN(install + repoint),RUNNER_REMOVE_TOKEN(remove + repoint) — including the two the issue undercounted. Remove/repoint correctly also name--local.no bare read -rsp remainsundercommands/is the load-bearing regression guard; per-command greps name the variables so a deleted guard cannot ship green.Checked
No blockers.
Verdict: I agree with everything and have no additional feedback.
All credential prompt sites now reject non-tty input with the exact unattended variable, guard interactive EOF, and preserve environment-variable bypasses. The broader sweep also covers both repoint prompts, and the current check and integration runs are green.
@danmt — handing this one to you. Final state:
What it fixes: rig#42 — every interactive credential prompt (
TS_AUTHKEYinbootstrap,RUNNER_TOKENinrunner install,RUNNER_REMOVE_TOKENinrunner remove, both tokens inrunner repoint) was a bareread -rsp. Headless (CI,box exec, any script),readfails,set -eends the run, and nothing prints — the release drill measuredrunner removeexiting 1 in total silence and a guest bootstrap whose log just stops. Each prompt now refuses first on no-tty, naming the exact variable that unblocks an unattended run (and--localwhere it applies), and everyreadis|| die-guarded so EOF at a real prompt also gets a last word.Review history: one round — all three bots approved with no changes requested. The sweep test (
no bare read -rsp under commands/) is what caughtrunner repoint's two prompts, which the issue had only counted as three.Verification:
test/cli.sh325/0 (3 grep-proof guard checks + the sweep) ·test/release.sh41/0 · shellcheck clean. The silent-death shape itself was reproduced live in the drill before the fix.No open questions from the round. Ready for your review.
🤖 Generated with Claude Code