Commit Graph
1953 Commits
Author SHA1 Message Date
kevinveenbirkenbach b1d38f49d6 Merge pull request #934 from infinito-nexus/fix/act/scope-outer-teardown
fix(act): remove only the own worktree's act containers
2026-10-15 10:51:48 +02:00
kevinveenbirkenbach 51d75fb804 Merge pull request #908 from infinito-nexus/fix/env/distro-derived-keys/794
fix(env): derive the image and container names from the distro under test
2026-10-15 10:50:59 +02:00
kevinveenbirkenbach 706745162b Merge remote-tracking branch 'origin/main' into fix/lint/mermaid-browser-revision 2026-10-15 10:36:09 +02:00
kevinveenbirkenbachandClaude Opus 5.5 cce4373abd fix(web-app-nextcloud): bound the onlyoffice check by a wall-clock deadline
`retries: 30` with `delay: 10` only bounded the wait while each
`occ onlyoffice:documentserver --check` failed fast. onlyoffice v10.2.1
gives the health check and the version command 60 s each and the
conversion 120 s, so a document server that accepts connections but
does not answer held the deploy for up to two hours before it failed.

The retries now also stop once a deadline of
`lookup('timeout', 300)` seconds, set right before the check, has
passed. A per-attempt `timeout:` would not bound the total: ansible-core
2.21 leaves the `until` loop on the first timed-out attempt, so only a
limit below onlyoffice's 60 s would end a hanging server's loop.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-15 04:04:33 +02:00
kevinveenbirkenbachandClaude Opus 5.5 c74a31e83e fix(lint): install the browser revision mmdc's own puppeteer pins
install-lint provisioned chrome-headless-shell with `npx --yes
puppeteer browsers install`, which runs the latest puppeteer from the
registry. mmdc runs with the puppeteer npm installed next to it as a
peer dependency when mmdc itself was installed, and looks for exactly
the revision that puppeteer-core pins. Once puppeteer 25.14.0 was out,
npx installed 155.0.8059.79 while mmdc with puppeteer-core 25.13.0
wanted 155.0.8059.39, and lint-mermaid failed on every file. Because
browser_installed() accepted any chrome-headless-shell, a stack with
the wrong revision never repaired itself.

The browser is now installed through the puppeteer CLI next to mmdc,
which installs its puppeteer-core's revision, and only that revision,
read from puppeteer-core's revisions.js, counts as installed.

Closes #957

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-15 03:21:30 +02:00
kevinveenbirkenbachandClaude Opus 5.5 778c18fb23 perf(constructor): carry the applications SPOT into the bootstrap roles
The constructor parked no applications carrier between the merge block
and the token store, so every lookup in the svc-swarm-node, svc-storage,
svc-registry and svc-virt bootstrap rendered the SPOT cold, 25 to 30 s
each on a loaded host.

A carrier there was unsafe: in swarm, svc-storage-nfs-server mounts the
NFS export over the controller's DIR_VAR_LIB, so the tokens file the
render reads can appear in the middle of that section, and the cache key
did not notice. merged_applications_cache_key now includes the tokens
file's path, mtime and size, as the users cache key already did, so a
carrier rejects itself once the tokens change. A carrier parked after
the add_host tasks then serves the bootstrap roles. It is parked only in
swarm mode: in compose the section runs in about a second, so a carrier
there would add a render without saving one.

In a swarm drill of web-app-prometheus up to the known NFS probe-write
failure, "Resolve the NFS server backend flavor" went from 29.6 s to
0.07 s, "Probe-mount the NFS export" from 26.4 s to 0.4 s, "Mount
cluster-shared infinito state on controller" from 23.7 s to 0.5 s and
"Ensure Docker-In-Docker DNS works" from 30.0 s to 3.6 s; the run to
that point took 768 s instead of 1735 s.

Closes #925

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-15 03:21:17 +02:00
kevinveenbirkenbach 1967a218d0 Merge remote-tracking branch 'origin/main' into dependabot/pip/ruff-0.17.0 2026-10-15 01:24:32 +02:00
kevinveenbirkenbachandClaude Opus 5.5 47565781ea style(python): import datetime as dt for ruff 0.17
ruff 0.17.0 adds `datetime` -> `dt` to the default aliases of
flake8-import-conventions, and the project selects ICN, so lint-python
failed with ICN001 in seven files.

The files now import `datetime as dt`. ruff's unsafe fix also renamed
two local names in utils/github/playwright_summary.py into the alias:
the `_to_iso_z` parameter and the parsed value in
`_parse_iso_timestamp`. Both are now called `moment`; with the bare fix,
nine tests of test_playwright_summary.py failed with UnboundLocalError
and AttributeError.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-15 01:24:31 +02:00
kevinveenbirkenbach e8ffe2536e Merge remote-tracking branch 'origin/main' into HEAD 2026-10-15 01:07:59 +02:00
kevinveenbirkenbach b637742f96 Merge remote-tracking branch 'origin/main' into fix/env/distro-derived-keys/794 2026-10-15 01:07:53 +02:00
kevinveenbirkenbachandClaude Opus 5.5 87c9a5f41b test(act): mark the docker stub log read as outside the file cache
The teardown test reads the call log its docker stub writes into a
temporary directory. test_no_uncached_file_reads flagged that read in
CI; the path-keyed read cache does not fit a file written per run, so
the read keeps Path.read_text with the cache-read opt-out, as the other
stub-log tests do.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-15 01:07:50 +02:00
kevinveenbirkenbach 06084d560a Merge remote-tracking branch 'origin/main' into fix/act/scope-outer-teardown 2026-10-15 01:07:50 +02:00
kevinveenbirkenbach 565e15f2a5 Merge remote-tracking branch 'origin/main' into fix/plugins/onion-apex-redirect/924 2026-10-15 01:07:47 +02:00
kevinveenbirkenbach 7344565df1 Merge remote-tracking branch 'origin/main' into fix/web-app-nextcloud/onlyoffice-settings-race 2026-10-15 01:07:41 +02:00
evangelostsak 8386823b2a Merge remote-tracking branch 'upstream/main' into feature/svc-net-wireguard
No conflicts. The 14 incoming commits fix the n8n gateway probe trigger under
n8n 2, let stalwart address bans expire, keep the Docker apt key when its
refresh is refused, leave eol roles out of image discovery, stop the release
backfill below the oldest buildable tag, and provision the mermaid browser
only in install-lint. None of them touches the mesh, swarm, NFS, network or
workflow files this branch changes.
2026-10-15 00:38:14 +02:00
kevinveenbirkenbach 365ea9e764 Merge pull request #911 from infinito-nexus/fix/web-app-prometheus/blackbox-verify/851
fix(web-app-prometheus): verify publicly trusted probe targets while the private CA is missing
2026-10-15 00:17:47 +02:00
evangelostsak 365d78462e test(swarm-test): extras read the interfaces list 2026-10-14 15:03:42 +02:00
evangelostsak 514a4e11b1 test(swarm-test): the round reads and hands over a layout 2026-10-14 15:03:42 +02:00
evangelostsak 789b1b10de test(swarm): render the advertise address through the real lookup 2026-10-14 15:03:42 +02:00
evangelostsak 01e8c1a75f test(lookup): mesh_address returns only the host's own primary address 2026-10-14 15:03:41 +02:00
evangelostsak b1279525bf test(mesh): the transport switch under a baked layout 2026-10-14 15:03:41 +02:00
evangelostsak 56ce03d370 test(mesh): the CLI reads its meshes from host_vars
Mesh names are asserted structurally: the baked layout names every mesh in
every file, so a substring match would pass on a host holding no interface.
2026-10-14 15:03:41 +02:00
evangelostsak a0a7436d19 test(mesh): the writer under a layout baked into host_vars 2026-10-14 15:03:41 +02:00
evangelostsak 54e237bddb test(mesh): plan against a topology instead of raw groups 2026-10-14 15:03:41 +02:00
evangelostsak e30b17276c test(mesh): declarations, pool and membership read from host_vars
Covers per-role and per-host membership, a host two roles put into one mesh,
the hub never being a spoke, an undeclared mesh being refused, and the
example's members matching its table.
2026-10-14 15:03:41 +02:00
evangelostsak 31cf7362d5 test(mesh): remove the contract tests with the contract 2026-10-14 15:03:41 +02:00
kevinveenbirkenbachandClaude Opus 5.5 46373c1ba3 fix(act): remove only the own worktree's act containers
down_act_outer.sh removed every container named act-*, so starting or
releasing a swarm drill in one worktree killed the act container of a
drill another worktree had running.

workflow.sh now labels act's job containers with
infinito.worktree=${INFINITO_CONTAINER} through the default
ACT_CONTAINER_OPTIONS, and down_act_outer.sh removes only containers
carrying the own label. Both scripts refuse to run without
INFINITO_CONTAINER, so the filter never widens to every act container;
make exports BASH_ENV, which loads it from .env.

Worktrees without a custom.env share the default container name and
therefore still share one label among themselves.

Closes #933

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-14 13:50:07 +02:00
kevinveenbirkenbachandClaude Opus 5.5 45732329b6 fix(lookup): keep the onion apex from redirecting to a clearnet homepage
On a Tor node current_play_redirect_domains schedules the bare node
onion as a redirect source targeting DOMAIN_HOMEPAGE. Without
web-app-dashboard, DOMAIN_HOMEPAGE falls back to SOFTWARE_DOMAIN
(infinito.nexus), so web-opt-rdr-domains rendered a 301 from
http://<node>.onion/ to http://infinito.nexus/: an onion visitor sent
to a clearnet host over plain HTTP.

The onion apex entry is now added only when DOMAIN_HOMEPAGE is an
onion host. Otherwise the onion apex gets no redirect and the default
server answers.

Closes #924

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-14 13:35:29 +02:00
kevinveenbirkenbachandClaude Opus 5.5 bfaa834f29 fix(web-app-nextcloud): write onlyoffice's server URL last and recheck it
The role writes onlyoffice's settings with one occ call per key,
DocumentServerUrl first and jwt_secret fourth. Nextcloud loads app
config once per process, so a cron.php that starts inside that batch
runs onlyoffice's EditorsCheck job, registered when the app was
enabled, with the document server URL but without the secret. The
document server answers "Invalid token", EditorsCheck stores it in
settings_error, and onlyoffice stops loading its Files integration;
EditorsCheck itself skips every later run while that error is set.

Seen in run 38455782184 (Nextcloud#4, swarm): cron.php started at
06:50:00 inside the batch that ran from 06:49:59 to 06:50:04, logged
"Invalid token" at 06:50:22, and both Playwright passes found .docx
files offered for download only.

DocumentServerUrl is now written last, so a process that cached the
config before the batch ended sees no URL and EditorsCheck returns
early. After the batch, `occ onlyoffice:documentserver --check` sets
settings_error from a fresh check: a redeploy clears an error latched
earlier, and a document server that stays unreachable fails the
deploy. A unit test keeps the URL last.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-14 13:34:52 +02:00
kevinveenbirkenbach a3c8f31d07 Merge remote-tracking branch 'origin/main' into HEAD
# Conflicts:
#	roles/web-app-stalwart/README.md
2026-10-14 13:34:01 +02:00
evangelostsak 2f96b52580 test(swarm-test): extras bind swarm and NFS to the primary mesh 2026-10-14 11:23:23 +02:00
evangelostsak af74e70ac0 test(swarm-test): the round deploys the declarations it is pointed at
The transport tests pin INFINITO_SWARM_MESHES to the default, so an operator
.env pointing at an example does not change what they assert. A controller
link left by other declarations is removed before the controller joins, and
one outside the pool is left alone.
2026-10-14 11:23:23 +02:00
evangelostsak 4856bcd131 test(swarm): the advertise address follows the primary mesh 2026-10-14 11:23:23 +02:00
evangelostsak e9dbab5835 test(mesh): the contract shape carries the primary flag 2026-10-14 11:23:23 +02:00
evangelostsak 05dc4af041 test(mesh): the controller joins the first declared mesh by default 2026-10-14 11:23:23 +02:00
evangelostsak a521937794 test(mesh): no two interfaces of a host route one prefix
Covers the swarm lab under the three-mesh example, where the NFS server is a
spoke of two meshes, and generated topologies of one to eight meshes.
2026-10-14 11:23:23 +02:00
evangelostsak 06cc872c1c test(mesh): pin how the primary mesh is chosen 2026-10-14 11:23:23 +02:00
evangelostsak 762513ec32 test(lookup): hold mesh_ranges to a rendered pool
The declared template must come back rendered, and one that stays a template
must fail rather than reach the export list.
2026-10-14 11:23:23 +02:00
Prageeth Panicker 06f0b42f12 Merge remote-tracking branch 'origin/main' into feature/web-app-wazuh/add-role 2026-10-14 09:00:39 +00:00
kevinveenbirkenbach 67b508cc5d Merge pull request #918 from infinito-nexus/fix/images/retired-role-discovery
fix(images): leave eol roles out of image discovery
2026-10-14 10:04:03 +02:00
kevinveenbirkenbach e6b88662be Merge pull request #919 from infinito-nexus/fix/ci/release-backfill-floor
fix(ci): stop the release backfill below the oldest buildable tag
2026-10-14 10:02:04 +02:00
kevinveenbirkenbach 7b80a807ab Merge pull request #909 from infinito-nexus/fix/lint/mermaid-browser-install/795
fix(lint): provision the mermaid browser in install-lint, not in the parallel lint run
2026-10-14 08:59:04 +02:00
kevinveenbirkenbachandClaude Opus 5.5 078d0a0682 fix(lint): provision mmdc's browser only when it is missing
install-lint provisioned chrome-headless-shell on every run, and `make lint`
runs install-lint once per lint target in parallel whenever its stamp is not
fresh. On CI the stamp never is (eslint lives in node_modules, not on PATH),
so one lint job provisioned 16 times (run 38455552981). As root, puppeteer's
--install-deps runs `apt-get satisfy` even for an installed browser, and two
of those at once fail on the dpkg lock; a failed provisioning then deleted the
shared browser cache while lint-mermaid could be rendering with it.

The browser is now provisioned only when it is not installed, and --force
drops its cache so `make install-lint-force` still reinstalls it with its
libraries.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-14 08:56:59 +02:00
kevinveenbirkenbachandClaude Opus 5.5 fd9286b24f test(lint): mark the stub call log as written by the test
test_no_uncached_file_reads rejects Path.read_text in tests unless the file is
written in the test itself. The mermaid script test reads the call log its
stubs append to during the run, so that read carries `# nocheck: cache-read`.
The mermaid cli test is formatted with ruff.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-14 01:32:35 +02:00
kevinveenbirkenbachandClaude Opus 5.5 ee8d2bd983 test(env): check each distro's parent image against its own reference
The loop test only required three different parent images for three distros,
which a swap between two of them would still pass. Each iteration now also
records the owner and tag it sees, and its image must equal
pkgmgr_image(distro, owner, tag). With the loader of main the test fails on
arch with pkgmgr-debian:stable.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-14 01:32:24 +02:00
kevinveenbirkenbachandClaude Opus 5.5 1d970fe5bd fix(env): keep shellcheck and the cache-read lint green on the distro switch
The loader copies INFINITO_DISTRO into a loader-local variable before it
compares the value with the one in .env. With INFINITO_DISTRO read directly in
that condition, `shellcheck -x scripts/meta/resolve/apps.sh` reported SC2153
for INFINITO_DISTROS, which apps.sh takes from the sourced .env; with the copy
it reports nothing, as on main.

The loader test checks that .env is unchanged with filecmp against the file it
was copied from, instead of reading it twice with Path.read_bytes, which
test_no_uncached_file_reads rejects.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-14 01:32:24 +02:00
kevinveenbirkenbachandClaude Opus 5.5 d412b23409 fix(ci): stop the release backfill below the oldest buildable tag
The release backfill dispatches the highest version tag whose images are
missing. Every tag from v15.0.0 down to v9.0.2 has its images now, so since
2026-10-05 it picks v9.0.1 every day, and each of the nine runs failed in
"Build missing CI images / Image" at
`entry.sh: line 19: infinito: command not found`. The v9.0.1 tree cannot
build its own image; c680be12ea fixed that build in v9.0.2, and a tag cannot
take the fix.

highest_release_tag.sh now stops at v9.0.2: no tag below it is picked, so the
backfill reports nothing missing instead of retrying v9.0.1. v9.0.0 has the
same Dockerfile, Makefile and scripts/docker as v9.0.1.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-14 01:32:05 +02:00
kevinveenbirkenbachandClaude Opus 5.5 8a29ba0bfd fix(images): leave eol roles out of image discovery
The scheduled mirror job has failed every day since 2026-09-25 on the same two
images: quay.io/minio/minio and quay.io/minio/mc answer `unauthorized` to
anonymous pulls ("2/197 failed", run 38352569503). Both belong to
web-app-minio, an eol role outside the lifecycle envelope that default.env
tests, so no CI deploy pulls them.

iter_role_images now skips every role that is_maintained() reports as
unmaintained, the check the version updaters already apply to the same list.
On the tree the discovery yields 187 images instead of 192; the five it drops
belong to the four eol roles web-app-confluence, web-app-jira, web-app-minio
and web-app-phpldapadmin. The mirror sync, resolver and wait read this list,
and their descriptions and mirror.md now say so.

The roles directory is resolved first: is_maintained reads a relative path as
a role name and would keep every role.

475ab9b386 on feature/store-i18n takes the same approach with a lifecycle
reader of its own; main already has is_maintained for it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-14 01:19:28 +02:00
evangelostsak 93ab3f326c test(ci): hold both mesh arms inside every default sweep
Eight compose-or-swarm rows over eight sweeps: each sweep must put swarm rows
on the meshed and the direct arm, and no compose row may carry the mesh. Fails
on the previous wants_vpn, which held every swarm row of a sweep on one arm.
2026-10-14 00:27:17 +02:00
evangelostsak e043ad0c00 test(mesh): zip the planned meshes strictly against their specs
The any-number-of-meshes test zipped the specs against the planned meshes
without strict=, which ruff reports as B905 and the lint-python job failed on.
Both sequences come from the same declarations, so strict=True also turns a
plan that drops a mesh into a failure instead of a silently shorter loop.
2026-10-14 00:27:17 +02:00