teardown-host.sh has no [ -t 0 ] gate: a non-interactive run without --yes dies mute #113
Labels
No labels
blocked
blocker:ci-red
blocker:conflict
blocker:drill-pending
blocker:unrequested
bug
claimed
documentation
enhancement
epic
merge-next
needs-triage
ready
release
scope:cli
scope:drill
scope:host
scope:installer
scope:templates
scope:tiers
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/box#113
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
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?
Split out of #112, where
claude-bot-andresmgslfound it while reviewing the #111 EOF sweep. The EOF half is fixed in #112; this is the other half, and it is a different defect.What
host/teardown-host.sh:31asks its confirmation like this:There is no
[ -t 0 ]check anywhere before thatread. So a non-interactive run without--yes/BOX_YES— a CI job, a pipe, anohup, anything without a terminal — falls straight intoread, gets immediate EOF, and now (post-#112) printsabortedand exits 1.That is no longer silent, which is what #112 fixed. But it is still the wrong contract. Every other destructive gate in the repo refuses a terminal-less run with a message that says why and points at the override:
host/revoke-user.sh:44-47—refusing to --purge without a terminal to confirm on. BOX_YES=1 means yes., exit 2bin/boxconfirm()— same shape, refuses on[ -t 0 ]failinginstall.sh:54-65— documents the contract and reads/dev/ttydirectlyteardown is the most destructive script in the tree — all boxes, both network generations, profiles, firewall units, optionally apt-purging Incus — and it is the one that does not tell a non-interactive caller how to proceed. It just says
aborted.Suggested fix
Mirror
revoke-user.sh, which is the closest sibling and already has the right shape:Note the exit code:
2for "you invoked this wrong", matching revoke and box's own usage-error convention, versus1for "you were asked and you refused".Why it was not folded into #112
#112 is scoped to the silent-EOF class: an unguarded
readunderset -ethat dies before it can name the abort. That is one token per site and it is now swept repo-wide bytest/cli.sh. This is a missing precondition — a different shape, a different exit code, and it changes the refusal contract of a script CI calls (box uninstall --purge-hostand the uninstall drill both run teardown unattended, though both pass--yes, so both are unaffected). It deserves its own diff and its own test rather than riding along.Worth checking whether any caller relies on the current fall-through before changing the exit code.