Commit Graph
8 Commits
Author SHA1 Message Date
kevinveenbirkenbachandClaude Opus 5 104ef5e9d0 fix(compose): keep the runtime's resolver so a compose alias still resolves
Naming a dns server replaces the runtime's embedded one rather than adding
to it, and that embedded server is the only thing answering compose
aliases. The dev container could therefore not look up `tools`, so every
check reaching a lane service by its service name reported that nothing
answers and skipped itself: the System One suite skipped with 325 usable
pairs behind an address it could not resolve, while its service was up and
healthy.

The embedded resolver goes after the platform one, so platform names
resolve where they always did and only what that server does not know falls
through.

Its address is the one group_vars/all/08_networks.yml already holds, read
through the env pipeline rather than written a second time in compose.yml.
`read_group_path` only ever read the paths file, so the reader it is built
on now takes the file to read and it keeps its own signature.

The two docker handlers share a prefix once a second one exists, which is a
folder; they move into one.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-29 11:45:55 +02:00
kevinveenbirkenbachandClaude Opus 5 fc0881ff33 fix(env): point python at the OS trust store
The package-cache frontend terminates TLS for package traffic and signs
with its own CA: probed from inside the test container, pypi.org arrives
as subject CN=pypi.org issued by CN=Infinito Package-Cache Frontend CA.
package-frontend-ca.sh installs that CA into the OS store, which is why
apt, pip, curl and urllib work — but requests reads certifi, which has
never heard of it, so test-external failed its reachability precondition
with CERTIFICATE_VERIFY_FAILED. Upgrading certifi does not help; the
issuer is not a public root.

load.sh is where the runner puts the venv on PATH, so it is also where the
interpreter carrying the pip certifi is chosen; pointing REQUESTS_CA_BUNDLE
and SSL_CERT_FILE at the store the stack deliberately fills keeps one trust
decision instead of two. A caller-set value still wins.

The bundle location was about to become a fourth copy: dev-nix and the
network diagnose CLI each carried their own candidate list, and the two had
already drifted apart in their fourth entry. All of them now read
group_vars CA_BUNDLE_CANDIDATES — Ansible directly, the shell through a
generated env key, python through read_group_paths.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-22 18:55:58 +02:00
kevinveenbirkenbachandClaude Opus 4.8 ab3accba3a refactor(paths): derive var-lib subpaths everywhere from the paths SPOT
Add DIR_BACKUPS to utils.paths and INFINITO_DIR_BACKUPS /
INFINITO_DIR_SECRETS env handlers, derive the recover-console constants
(including NFS_EXPORT_STATE) from utils.paths and the nfs export SPOT,
and switch every remaining self-built /var/lib/infinito subpath - the
secrets recover targets, the swarm extras backup source, the users
token-store candidate chain, the CI recover drill, the swarm NFS
diagnostics and the playwright reports dir - to those constants. Tests
consume the env constants directly; narration comments in the touched
files are dropped per the comment lint.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 16:15:27 +02:00
kevinveenbirkenbachandClaude Opus 4.8 63b60b00bb fix(env): parse the group_vars paths SPOT without PyYAML
The new dir handlers pulled utils.cache.yaml into the env build, which
bootstrap runs (make install-system-python) before any Python dependency
exists; on arch and manjaro, whose images ship no preinstalled PyYAML, the
.env generation died with ModuleNotFoundError and broke PKGMGR and the dev
environment jobs. Read the plain KEY: "value" entries with a stdlib line
parser instead; Jinja values and missing keys stay hard errors.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-11 03:26:13 +02:00
kevinveenbirkenbachandClaude Opus 4.8 094c02a69d feat(diagnostics): single SPOT rescue script with CI-uploaded snapshots
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>
2026-07-11 03:04:06 +02:00
kevinveenbirkenbachandClaude Opus 4.8 398d4d11b0 fix: satisfy make test on bundles 1/6/7 (cached read, ansible-lint-ignore, ruff wrap)
These commits were made with --no-verify, which skipped make test, leaving three latent lint failures. utils/paths.py: use the cached utils.cache.files.read_text (verified no import cycle) instead of a plain read. .ansible-lint-ignore: add the pixelfed resolve_host_cid load-failure entry (templated playbook_dir include, false positive). library/database_query.py: ruff line-wrap. make test is now fully green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 22:55:57 +02:00
kevinveenbirkenbachandClaude Opus 4.8 c9886f2f69 fix(utils-paths): resolve INFINITO_DIR_VAR_LIB from default.env when env unset
The compose-deploy inventory validator is spawned as a bare subprocess without the env build, so os.environ["INFINITO_DIR_VAR_LIB"] raised KeyError at import and aborted all compose deploys before Ansible ran. Fall back to the default.env SPOT (no hardcoded literal); read it plainly to avoid a utils.paths -> utils.cache import cycle.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 22:02:16 +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