Skip to content

feat(healthcheck): decouple host liveness from the self-update loop#34

Merged
jcardozo-eth merged 3 commits into
mainfrom
feat/decouple-healthcheck-self-update
Jul 23, 2026
Merged

feat(healthcheck): decouple host liveness from the self-update loop#34
jcardozo-eth merged 3 commits into
mainfrom
feat/decouple-healthcheck-self-update

Conversation

@jcardozo-eth

@jcardozo-eth jcardozo-eth commented Jul 23, 2026

Copy link
Copy Markdown
Member

Closes #14.

Summary

The host healthcheck previously installed only with the self-update loop (standalone.self_update.manage), so a standalone host that applies manually rather than on a timer had zero health monitoring. This splits the healthcheck into two layers: liveness, which installs on any declared-standalone host, and loop supervision, which layers on only where the self-update loop drives convergence. One script, one timer, no new toggle.

What changed

The healthcheck script, service, and timer now install under standalone.manage alongside the apply script. templates/healthcheck.sh.epp renders an always-present liveness section (manager service active, rootless docker user unit active, docker info as the runner user) and, only when self_update.manage is true, a supervision section (apply timer enabled and armed, checkout staleness against origin, and a new assertion that the bootstrap gems r10k and hiera-eyaml are present in the AIO Ruby). The staleness check stays loop-gated because a manually-applied host is legitimately behind origin between applies.

runner_account.uid is now required wherever the healthcheck installs (standalone.manage), since the liveness probe derives the rootless runtime paths from it. The daemon-reload exec that the healthcheck units need moved up under standalone.manage and is retitled accordingly; the apply units keep notifying it (sound because self_update.manage implies standalone.manage). Unit names and the script path are unchanged.

Behavior

  • Standalone, loop off: gains a liveness timer (manager service, rootless daemon), including when the module owns neither (externally-owned account).
  • Standalone, loop on: liveness plus the loop-supervision checks (apply timer enabled and armed, checkout staleness, bootstrap gems).
  • Fleet (no standalone): nothing new installed; catalog byte-identical to before.
  • Loop without standalone: still fails at compile time.

Testing

just check is green (validate, lint, 125 rspec examples, docs-check). Catalog tests cover all three states: no standalone (nothing installed), standalone without the loop (healthcheck installed, rendered script contains liveness only), and standalone with the loop (full script, including the gem assertion). The rendered-script split and the moved uid guard are each mutation-checked. The golden healthcheck fixture is regenerated from the template.

Docs

  • Updated: README.md.
  • Updated: REFERENCE.md.
  • Added: a CHANGELOG.md entry under "Changed" describing the consumer-visible behavior.

The healthcheck (script, service, timer) now installs with standalone.manage,
so a standalone host without the self-update loop still monitors its manager
service and rootless docker daemon. The loop-supervision checks (apply-timer
state, checkout staleness, and a new bootstrap-gem assertion) render into the
script only under self_update.manage. runner_account.uid is now required
wherever the healthcheck installs (standalone.manage).
@jcardozo-eth jcardozo-eth self-assigned this Jul 23, 2026
@jcardozo-eth
jcardozo-eth merged commit f297a33 into main Jul 23, 2026
3 checks passed
@jcardozo-eth jcardozo-eth added this to the 2.0.0 milestone Jul 24, 2026
@jcardozo-eth jcardozo-eth added breaking Breaking change: lands only in a major release enhancement New feature or request labels Jul 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

breaking Breaking change: lands only in a major release enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Decouple the host healthcheck from the self-update loop

1 participant