install: derive $HOME from getent when the environment has none (#39) #41
No reviewers
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#41
Loading…
Reference in a new issue
No description provided.
Delete branch "fix/home-unset"
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?
Closes #39.
cloud-init's
runcmdcarries no$HOME, andinstall.sh(set -euo pipefail) died on its first$HOMEexpansion with a bash unbound-variable stack — found live while e2e-testing box#88's seed, which pinsHOME=/rooton its install line as its own scar (that pin stays; this makes the installer robust for every other caller).The fix (
install.sh, before any path derivation): when$HOMEis unset, derive it fromgetent passwdfor the effective uid (works for root and non-root); when getent has no answer either, refuse by name (set HOME and re-run) instead of a stack trace.|| trueon the pipeline so pipefail can't turn the no-answer case into an unnamed death — the refusal owns it.Verification
test/cli.sh: 321 passed, 0 failed (main baseline 318; +3: a real driven install withenv -u HOMEand a shim getent landing the tree under the derived home; the no-answer refusal pinned by message and exit code).shellcheck -x(CI's invocation): clean.🤖 Generated with Claude Code
✅ Reviewed — I agree with all of this, no concerns.
First review — a focused fix for #39: cloud-init's
runcmdcarries no$HOME, so underset -euo pipefailthe first$HOMEexpansion died with an unbound-variable stack instead of installing. Things I checked that could have been bugs but aren't:set -e/set -utrap is handled correctly. The guard runs before any path is derived from$HOME, and${HOME:-}in the[ -z ]test avoids tripping-uwhile probing.HOME="$(getent passwd "$(id -u)" | cut -d: -f6 || true)"— the|| trueis load-bearing:var=$(cmd)propagates the command's exit status toset -e, so without it a getent that exits nonzero (no entry, or getent absent) would kill the script with its code before reaching the named refusal. With it, the substitution yields empty and the explicit[ -z "$HOME" ]refusal owns every no-answer case — never a bare stack.getent passwd $(id -u)is the right lookup, keyed on the effective uid, so it resolves for root and non-root alike; field 6 (cut -d: -f6) is the home dir. A colon can't appear in a passwd home field, so the cut is safe.set HOME and re-run) and the uid, exits 1, no side effects.test/cli.sh:973drives a realenv -u HOMEinstall through a shim getent and asserts the tree lands under the derived home;:987swaps in anexit 2getent and pins the by-name refusal + exit 1. 321 passed (main baseline 318, +3),shellcheck -xclean.The box#88 seed's
HOME=/rootpin correctly stays as its own scar; this makes the installer robust for every other caller. Ready to land.— automated review by
claude-bot-andresmgsl· heavy-duty-review-botVerdict: Approve — I agree with this as-is.
Focused fix for #39: cloud-init
runcmdhas no$HOME, and underset -euo pipefailthe first$HOMEexpansion was a stack instead of an install.Checked
$HOME;${HOME:-}in the probe avoids tripping-u.|| trueon the getent pipeline — load-bearing under pipefail: a no-answer getent would otherwise kill the script with its exit code before the named refusal. With it, empty HOME falls through to the explicit message + exit 1.getent passwd $(id -u)field 6) — correct for root and non-root; passwd home fields cannot contain:, socut -d: -f6is safe.env -u HOMEinstall via shim getent lands under the derived home;exit 2getent pins by-name refusal + exit 1.box#88's
HOME=/rootpin correctly stays as its own scar. Ready to land.Verdict: I agree with everything and have no additional feedback.
The fallback runs before any HOME-derived path, safely probes an unset variable under
set -u, resolves the effective user throughgetent, and turns a missing lookup into an actionable failure. The tests cover both successful derivation and refusal, the linked cloud-init scenario is addressed, and all current checks pass.Round 1: unanimous (codex ✅ / grok ✅ / claude ✅-agree, nothing outstanding). CI green. Requesting @danmt for final review.