fix(installer): symlink bundled node/npm into command bin dir for FHS root installs - #38889
Conversation
… root installs Root installs on Linux (FHS layout, #15608) put the `hermes` command in `/usr/local/bin` (on PATH) but symlinked the bundled node/npm/npx into `~/.local/bin`, which isn't on PATH for a stock root shell. `node`/`npm` were 'command not found' and `hermes dashboard` failed with 'npm is not available' because its build-on-demand fallback couldn't find npm. Fix: `install_node()` now symlinks into `get_command_link_dir()` — the same helper the `hermes` command link already uses — so node/npm/npx land wherever the command does (`/usr/local/bin` on FHS root, `~/.local/bin` otherwise, `$PREFIX/bin` on Termux). Non-root and Termux installs are unchanged. Also fixes: - `scripts/lib/node-bootstrap.sh`: adds `_nb_get_link_dir()` mirroring the same root/Termux/user logic for the standalone bootstrap path (used by `hermes update`, TUI node bootstrap, etc.) - `hermes_cli/uninstall.py`: `remove_node_symlinks()` now checks all candidate directories (`~/.local/bin`, `/usr/local/bin`, `$PREFIX/bin`) so root FHS uninstalls don't leave orphan symlinks Regression from #15608, which created the FHS path for the command but left `install_node` pointed at the legacy user-local dir.
🔎 Lint report:
|
Review response — hardening + scope decisionsThanks for the sharp review. Addressed the high/medium items in commit Fixed#1 Existing-broken-install → update/migration (the trap). Confirmed and fixed. #2 Stale #4 Parity. Doctor now catches this regression class (it previously couldn't): Bonus FHS bugs found in the audit + fixed: profile-alias wrappers ( Verified (throwaway Ubuntu 24.04 VM, libvirt)A scenario matrix (fresh-root / migration / fresh-nonroot / uninstall), run against the patched
#7 dashboard
|
Summary
Root installs on Linux (FHS layout, #15608) put the
hermescommand in/usr/local/bin(on PATH) but symlinked the bundled node/npm/npx into~/.local/bin, which isn't on PATH for a stock root shell. Result:node/npmare "command not found" andhermes dashboardfails with"npm is not available".
Root Cause
install_node()(scripts/install.sh:845) hardcodes$HOME/.local/binfor thenode symlinks. But
get_command_link_dir()— the helper thehermescommandalready uses — correctly returns
/usr/local/binfor root FHS installs.PR #15608 created the FHS path for the command but left
install_nodepointedat the legacy user-local dir.
The PATH-guard (install.sh:1538+) doesn't self-heal this because it checks
$command_link_dir(=/usr/local/bin, already on PATH), so it's a no-op forthe exact case that needs it.
Fix
scripts/install.sh:install_node()now symlinks intoget_command_link_dir()— same helper thehermescommand link uses./usr/local/binon FHS root,~/.local/binotherwise,$PREFIX/binon Termux.scripts/lib/node-bootstrap.sh: new_nb_get_link_dir()mirrors thesame logic for the standalone bootstrap path (used by
hermes update, TUInode bootstrap).
hermes_cli/uninstall.py:remove_node_symlinks()now checks allcandidate directories so root FHS uninstalls don't leave orphan symlinks in
/usr/local/bin.Non-root and Termux installs are unchanged (same symlink target as before).
Reproduction & Verification
Tested on a clean Ubuntu 24.04 VM (libvirt, cloud image):
curl | bash)/root/.local/bin/(not on PATH)/usr/local/bin/(on PATH ✓)command -v nodein stock root shell/usr/local/bin/node✓hermes dashboardTest Plan
test_removes_fhs_symlinks_in_usr_local_bincovers FHS pathnoderesolves →hermes dashboardbuilds + servesInfographic