Repository navigation
install.sh: install the deploy supervisor on checkout installs (timer off) - #1335
Merged
Merged
Conversation
… off Until now the deploy supervisor (deploy/from-main) was a separate once-per-box install from a README that no installer ran. Every box set up with deploy/fleet/install.sh therefore had a dashboard update button that could only fail with "Unit hestia-deploy.service not found" (#791: Nomad 2026-09-01, tl-dell 2026-10-16). The operator on tl-dell asked whether a brand-new install would "just work from the getgo"; it would not. New step_deploy_supervisor, run after the workspace marker: - checkout install (HESTIA_WORKSPACE resolved) with git + cargo on Linux: clones hestia + web4 into $HESTIA_HOME/deploy over https (the units run with no ssh agent), installs ~/.local/bin/hestia-deploy and both units with HESTIA_WORKSPACE rendered, reads the unit back, daemon-reload. - the TIMER STAYS OFF by default. HESTIA_AUTO_UPDATE=1 arms it. A re-run never disarms a timer the operator turned on. - skips, saying why: release (curl | sh) installs track releases, not main; missing git/cargo; macOS (launchd binary path derivation is not automated yet); HESTIA_SKIP_DEPLOY. deploy/fleet/deploy_supervisor_step_test.py runs the step itself in a temp HOME with stub git/cargo/systemctl/uname against the REAL shipped unit files: 17 checks, including "nothing asked systemd to enable the timer" by default. surface: deploy/fleet/install.sh step_deploy_supervisor act: install a supervisor that can deploy hestia main to this box S: med/reversible [construct: timer off by default; units removable; nothing builds until an operator act] R: n/a (operator-run installer, same trust as the rest of install.sh) W: n/a (no daemon surface; the deploy act itself stays behind operator_gate / the operator's own timer choice) O: pass [construct: prerequisites (checkout, git, cargo, Linux) checked before the first write] A: n/a (installer output; the deploy acts it enables are witnessed by the daemon) V: present [construct: hestia-deploy.sh preflight_gate + rollback, unchanged] verdict: PASS Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Owner
|
NOVA review follow-up (2026-10-17): HOLD: installer systemd Environment= path rendering mishandles spaces/special chars and custom HESTIA_HOME may not propagate into installed unit. Verify parsed unit with systemd-analyze and add non-default-home/path tests. |
…lt HESTIA_HOME Nova's HOLD on #1335 (2026-10-17): - The workspace went into the unit unquoted, through sed. systemd splits an unquoted Environment= value at whitespace, treats % as a specifier, and backslash and quote as syntax; sed reads | & \ in the path as its own. Measured on the old code with the new test: "My Projects" reached systemd as ".../My", "pipe|amp&x" broke sed, and in the space cases the step still printed "the dashboard update button works". Now `systemd_env_line` writes Environment="VAR=value" with \ " escaped and % doubled, awk substitutes it from the environment, the read-back is grep -F, and systemd-analyze verify (where present) must not complain about the environment. - A custom HESTIA_HOME was not followed: the step cloned into $HESTIA_HOME/deploy, but the shipped units run with HESTIA_HOME=%h/.hestia and hestia-deploy defaults its clones to ~/.hestia/deploy, as does the daemon unit this script installs. Rather than install a supervisor that clones into one home and deploys into another, the step now skips and names the manual route. deploy_supervisor_step_test.py: a model of systemd's Environment= parser checks six awkward workspace names round-trip with no stray variable, plus the HESTIA_HOME skip and a direct systemd-analyze verify of the rendered unit. 8 of the new checks fail on the previous commit. -- cbp-claude Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014LYVQN8U1xqy6U6pbyUDvH
Owner
|
Addressed Nova's HOLD in 5e5c552 (pushed onto this branch, no force):
— cbp-claude |
5e5c552's HESTIA_HOME guard spelled the default home out twice more, and the no-path-literals ratchet (CI, plugin tests) failed on it: shell-home-hestia 5 -> 6, tilde-hestia 0 -> 1. The default is now named once, as HESTIA_HOME_DEFAULT, on the line that already resolved it. The guard and its message use the variable. The pin moves by one reclassification (that line's shell-home-default becomes the existing shell-home-hestia count): 10 -> 9. -- cbp-claude Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014LYVQN8U1xqy6U6pbyUDvH
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
The operator on tl-dell asked: "on a BRAND NEW install, will that code have to be run or will it just work from the getgo?" It would not just work. The deploy supervisor that the dashboard's update button starts (
hestia-deploy.service) is a separate once-per-box install fromdeploy/from-main/README.md, and no installer runs it. So every box set up withdeploy/fleet/install.shgets an update button that can only fail withUnit hestia-deploy.service not found(#791: Nomad 2026-09-01, tl-dell 2026-10-16).Companion to #1334, which adds the dashboard's auto-update toggle and "check for updates" button and hides both where no supervisor is installed. This PR is what makes them present on a fresh box. The two PRs are independent and can merge in either order.
What
New
step_deploy_supervisorindeploy/fleet/install.sh, run after the workspace marker:HESTIA_WORKSPACE) with git and cargo, on Linux:$HESTIA_HOME/deployover https, since the units run without an ssh agent;~/.local/bin/hestia-deployand both units, withHESTIA_WORKSPACErendered into the service;daemon-reload.HESTIA_AUTO_UPDATE=1arms it at install time. A re-run never disarms a timer the operator turned on.curl | sh) installs: they track releases, not main, and are updated by re-running the installer. Converting them to main-tracking is a choice this step doesn't make for them.HESTIA_SKIP_DEPLOYis set.deploy/from-main/README.md: a note at the top of the Linux install section. The manual lines stay as the reference and as the opt-in route for release installs.Questions for review
Tested
deploy/fleet/deploy_supervisor_step_test.py(picked up bytools/ci_discovery.py bare): 17 checks. It runs the step itself in a temporary HOME, with stub git, cargo, systemctl and uname, against the real shippedhestia-deploy.{sh,service,timer}. It covers:install_version_test.py,tools/no_path_literals_test.py,tools/public_boundary.py,tools/ci_test_coverage_test.py,tools/shebang_exec_bit_test.py, and thedeploy/from-main/*_test.pyfiles all pass.install.shrun on a real fresh box. On this box it would replace the main-built daemon with a release binary.Review gate
🤖 Generated with Claude Code