Skip to content

Gate type-none components on their systemd unit - #107

Merged
shipmill-romamo[bot] merged 2 commits into
mainfrom
fix/96-healthcheck-none
Oct 20, 2026
Merged

shipmill-romamo[bot] merged 2 commits into
mainfrom
fix/96-healthcheck-none

Conversation

@shipmill-romamo

Copy link
Copy Markdown
Contributor

Summary

component.schema.json accepts healthCheck: {type: none} for a component that serves no HTTP (a queue worker), but the deploy role's gate always ran ansible.builtin.uri with healthCheck.scheme/port/path, which are undefined for none. The task failed, the rescue ran, and a first release was stopped.

  • The HTTP gate now runs only for type: http; its tasks are otherwise unchanged
  • For type: none, inside the same block, the gate requires the systemd unit to be active right after the restart, reads NRestarts, pauses for cloudfall_deploy_unit_settle_seconds (role default 10, not a schema field), then requires the unit to be still active with NRestarts unchanged. An inactive unit, a restart while settling (Restart=on-failure can bring a crash-looping worker back before the second check), or an unreadable count fails the task, so the existing rescue rolls back or stops a first release
  • Check mode still skips the gate. No schema change, no receipt change (healthCheckPassed records that the unit gate passed)
  • Changelog fragment changelog.d/96-healthcheck-none.md

Test plan

  • New engine/tests/test_deploy_role.py, in the style of test_time_role.py and test_nginx_site_role.py: it evaluates the role's when and that expressions with Ansible's own templating. It covers gate selection for http, none and check mode; both is-active tasks failing on a non-zero exit; NRestarts read from systemd; the no-restart assertion passing for unchanged counts and failing for a crash loop or an unreadable count; the 10 s default; and the rescue steps for a first and a later release. The selection tests fail on the old task file
  • uv run ruff check ., uv run mypy, uv run pytest (541 passed), uv run cloudfall config validate --project config/examples, uv run cloudfall-engine inventory render --project config/examples
  • Not run locally: ansible-playbook --syntax-check on deploy.yml and ansible-lint engine/ansible (CI's "Ansible syntax checks" and "Ansible lint" jobs run them). No live systemd run

Fixes #96

🤖 Generated with Claude Code

shipmill-romamo Bot and others added 2 commits October 20, 2026 12:34
A component declaring healthCheck: {type: none} (a queue worker with no
HTTP endpoint) passed schema validation, but the deploy role always ran
the HTTP uri gate with healthCheck.scheme/port/path, which are undefined
for none. The task failed, the rescue ran, and a first release was
stopped.

The HTTP gate now runs only for type http. For type none the gate
requires the service unit to be active right after the restart and
still active after a fixed settle time (role default
cloudfall_deploy_unit_settle_seconds, 10 s), so a worker that crashes
on start fails inside the block and goes through the same rescue and
rollback. Check mode still skips the gate; the receipt is unchanged.

Fixes #96

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The unit template sets Restart=on-failure, so a worker that crash-loops
can read as active at the second is-active check. The gate now reads
NRestarts before and after the settle pause and fails, inside the same
block so the rescue still runs, when it went up or is unreadable.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@shipmill-romamo
shipmill-romamo Bot merged commit a9167f5 into main Oct 20, 2026
1 check passed
@shipmill-romamo
shipmill-romamo Bot deleted the fix/96-healthcheck-none branch October 20, 2026 10:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

A component with healthCheck type none always fails its deploy

0 participants