Commit Graph
4 Commits
Author SHA1 Message Date
kevinveenbirkenbachandClaude Opus 5 508bc5adac test(lint): keep shell scripts out of jinja templates
A templated script is opaque to every tool that reads shell. shellcheck parses Jinja as syntax errors, the repository's own .sh guards skip the file because it is not a .sh, and nothing can execute it to test it: what runs on the host never exists in the repository, so a defect in the rendered half is found by deploying it.

The lint reports any *.sh.j2 under roles and points at the static slot sys-service already resolves, files/shell/script.sh, with the values passed as ExecStart arguments or Environment entries the way this repository's python scripts already take them.

None of the seven templates present meets the bar the marker is for, which is a script whose shape is generated rather than its values. Each is grandfathered with a marker naming what it interpolates, because converting a deployed script to argv changes what runs on the host. The guard exists to stop the next one.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-15 20:36:04 +02:00
kevinveenbirkenbachandClaude Opus 5 10da2c2699 fix(backup): name the provider that failed and keep its journal readable
The DR drill's remote pull exits 1 after 65 minutes and nothing says why. The
unit loops over two providers and only counts errors, so which one failed is
unrecoverable; the pull runs `rsync -abP`, whose --progress writes one journal
line per file - 77137 of them on a nextcloud pull - and the drill captured
`journalctl -n 60`. The entire diagnostic was therefore rsync filenames.

The unit now names the host it could not pull from. rsync keeps --partial and
trades --progress for --info=stats2, turning the flood into a closing balance.
trigger_units.sh writes the complete journal of a failed unit into the rescue
dump directory the artifact ships as local-dumps, and prints only the lines
from warning upwards.

That directory arrives as an argument instead of a second copy of the paths
SPOT: the drill reads INFINITO_RESCUE_DIAGNOSTICS_DIR once, which the env
handler derives from group_vars/all/05_paths.yml, and hands it to every call
site. A test pins that contract, and it earned its place immediately - it found
two call sites that a grep for the file name cannot see, and both were the
units this change exists for.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-01 02:13:23 +02:00
kevinveenbirkenbachandClaude Opus 4.8 cf765ee00c refactor: single /var/lib SPOT + swarm Playwright artifact upload
SPOT: declare the var-lib base once in default.env as INFINITO_DIR_VAR_LIB; the env build derives INFINITO_PLAYWRIGHT_REPORTS_BASE_DIR from it; reference it everywhere (utils/paths.py, scripts via ${...:?}, tests, the dev inventory's DIR_VAR_LIB injection) instead of hardcoding the literal. group_vars keeps the literal default; the env-lookup lives in the dev inventory per the no-ansible-env-lookups lint rule. pull_specific_host.py --folder is now required and the role passes {{ DIR_BACKUPS }}.

Swarm e2e: collect_playwright_reports.sh docker-cp's the reports off the manager plus a workflow upload step, so swarm Playwright traces reach CI artifacts (was compose-only).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 17:01:09 +02:00
kevinveenbirkenbachandClaude Opus 4.7 a08db7fa11 refactor(roles/svc-bkp-*): rename backup roles + make container/local-2-remote invokable
Consolidates the backup-role topology around four directional roles
under the existing svc.bkp category:

  sys-ctl-bkp-docker-2-loc  →  svc-bkp-container-2-local
  svc-bkp-loc-2-usb         →  svc-bkp-local-2-device
  svc-bkp-rmt-2-loc         →  svc-bkp-remote-2-local
  sys-bkp-provider          →  deleted (purely a bundler with no own logic;
                                the two pieces it pulled in — user-backup
                                and sys-timer-cln-bkps — are now declared
                                directly by callers that need them)

Every renamed role moves into svc.bkp (already invokable per
roles/categories.yml), gets an `application_id` in vars/main.yml, and
declares the per-app primary-entity service flags + resource limits the
invokable-role lint requires.

Companion changes:

  - svc-bkp-container-2-local: meta/variants.yml declares three matrix
    rounds (gitea+keycloak, postgres+mariadb, openldap) that pin the
    companion topology via service-key flags the CombinedResolver
    translates into provider-role includes.

  - sys-svc-compose: container-2-local is no longer in the docker-mgmt
    include loop; it joins via a separate `'svc-bkp-container-2-local'
    in group_names` gate so the 3 backup roles are deployable
    independently (each addresses its own failure mode).

  - The three `04_seed-database-to-backup.yml` includes (web-app-matrix,
    web-app-bigbluebutton, sys-svc-rdbms) are gated by the same
    group_names check so consumer apps only seed when the container
    backup is actually in scope.

  - web-app-gitea picks up `enabled: true, shared: true, provides:
    gitea` on its primary entity so the service registry can pull it in
    via a `services.gitea.enabled+shared` flag (needed for the
    container-backup variant 0).

  - group_vars constants and the pyproject ruff per-file-ignore + the
    .ansible-lint-ignore paths follow the role-id rename.

  - The remote-2-local script picks up the snake_case rename
    (`pull-specific-host.py` → `pull_specific_host.py`) and the
    `os.makedirs` → `Path.mkdir` conversion so the role no longer needs
    the PTH/N999 ruff escape hatch.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-23 04:23:45 +02:00