The deploy CLI shipped every mode as -e KEY=value, which ansible-playbook parses as a string at the highest precedence. MODE_DEBUG=false therefore arrived as the non-empty, and so truthy, string false. Every when: MODE_X | bool was unaffected because the filter maps it back, but four sites read a flag bare and silently inverted: openldap wrote LDAP attributes with state exact on every deploy instead of only under MODE_CLEANUP, SYS_SERVICE_DEFAULT_STATE was restarted where it should have been omit, SYS_SERVICE_RUNNER_STATE was never started, and mailu always logged at DEBUG.
Send the modes as one JSON extra-var, which keeps the declared type, and give those four sites the | bool they were missing so the meaning of a flag no longer depends on how its value reached Ansible. A lint pins the rule: a MODE_* read in a truthiness position carries the filter or a nocheck naming a genuine string comparison.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
10x60s reaped services whose healthcheck start_period legitimately exceeds ten minutes (suitecrm first boot declares twenty); 25x60s covers the longest declared start_period with margin. The loop still exits early on success and fails loudly after the budget.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Every Ansible rescue: block used to carry ad-hoc per-role failure dumps that
drifted apart and captured different subsets. Replace them all with one
diagnostics script (scripts/system/diagnostics/rescue.sh) that snapshots
containers (full logs plus inspect per container), swarm services (ps plus
logs per service), journal, host resources, runtime info and stats into a
per-run folder and always exits 1 so the deploy still fails. A new lint
enforces the shape: every rescue ends with the script, at most one
nocheck-justified extra task before it (postgres pg_hba dump, xwiki
extension-repo probe), and a nocheck rescue-recovery exemption for the one
block that must genuinely recover: keycloak object updates, where a
cross-node reschedule needs a swarm-wide node re-resolve plus a delegate_to
change that only a rescue can express; its recovery is kept and now also
captures diagnostics before the terminal failure.
The snapshot folder path is a group_vars SPOT: DIR_RESCUE_DIAGNOSTICS and
DIR_VAR_LIB live in group_vars/all/05_paths.yml as plain strings; new env
handlers derive INFINITO_RESCUE_DIAGNOSTICS_DIR and INFINITO_DIR_VAR_LIB
from it for the generated .env, replacing the default.env entries, and the
play-level environment forwards the value to every task host so rescue.sh
needs no second default. CI uploads the folder like the inventory and
playwright artifacts: compose copies it out of the deploy container in
dedicated.sh, swarm captures per node (manager and both workers) into
node-named subfolders.
Deleting the ad-hoc dumps orphaned helper files (postgres inspect_container,
terminator docker_diagnostics, peertube diagnostics, matomo bootstrap debug,
xwiki and openresty rescue includes) and 14 role vars; all removed. Generic
pieces of those dumps (runtime version and info, stats, dmesg oom evidence,
swapon) moved into the SPOT script instead.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Makefile lint integration:
* scripts/install/lint.sh: replace the prior checkmake binary install with
ensure_mbake (mbake is pip-installable, parses our Makefile correctly
whereas checkmake bailed on .ONESHELL: / .SHELLFLAGS: / ifneq).
* scripts/lint/makefile.sh: new runner — `mbake format --check Makefile`
reports formatting drift and missing .PHONY declarations.
* scripts/lint/autoformat.sh: add a two-pass `mbake format Makefile`
(mbake's formatter is not strictly idempotent on the first pass).
* Makefile: split the multi-line `.PHONY:` block into 18 single-line
`.PHONY:` declarations so mbake's parser can validate it; add the
previously-missing `install-python-dev` and `build-dependency` PHONY
targets; add `lint-makefile` aggregate-and-direct target.
* .pre-commit-config.yaml: new make-lint-makefile hook scoped to
`^Makefile$`.
* .github/workflows/lint-makefile.yml: new CI workflow (pip-install mbake
+ make lint-makefile).
* .github/workflows/ci-orchestrator.yml: wire lint-makefile into
lint-gate.needs.
Misc:
* .gitignore: add roles/importer_result.json (tooling artefact written by
galaxy-importer when it runs in roles/).
Plus working-tree drift across roles/, group_vars/, inventories/, and
tasks/ that accumulated from the make-test setup phase regenerating
generated artefacts during recent test runs.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Rename sys-service-runner to sys-service-terminator
- Add deploy-wide timer lockdown using SOFTWARE_NAME-based unit matching
- Mask timers and stop services during deploy, unmask and re-enable timers at finalization
- Ensure deterministic end-of-deploy service execution with diagnostics
https://chatgpt.com/share/697e595b-f378-800f-9f2b-5c5f416c2981