A defaulted build argument answers a question the caller failed to answer. The
build then succeeds against a base image, version or path nobody chose, and the
mistake surfaces as wrong behaviour at runtime instead of a failed build.
web-app-bridgy-fed shows the cost: its metadata declared python 3.14 while the
Dockerfile default silently built against 3.12. Both look plausible, so nothing
pointed at the drift. It and web-app-postmarks now take the base image from the
same services declaration the rest of the role reads.
The lint walks every tracked Dockerfile, template variants and paths outside
roles/ included, which the existing ARG-scope check does not. A second
assertion fails when the scan finds no Dockerfile at all, so the rule cannot
pass vacuously if the walk ever breaks.
Touching the two Dockerfiles brought their pre-existing narration under the
comment lint; what carried substance moved into the file header.
Resolves the runner Dockerfile to the lint-standard Acquire::Retries=3
and keeps the collabora TODO wording; hardens the merged tree for the
stricter lints (apt retries in the tor Dockerfile, shell-or-true
markers, comment cleanup).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A transient Debian/Ubuntu mirror fetch aborts a docker build layer with exit 100 (it killed the web-app-nextcloud swarm openldap build while the same image built fine elsewhere). New lint under tests/lint/docker/dockerfile/apt/ flags any RUN with apt-get update/install that omits Acquire::Retries; retrofit all 15 apt Dockerfiles with -o Acquire::Retries=3. Both apt lints move into the apt/ subpackage. dnf retries by default and apk has no equivalent flag, so both stay out of scope.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Turn the oauth2-proxy/Keycloak identity into a real app session (pattern from web-app-baserow/bookwyrm) so proxy-gated visitors land authenticated instead of on the app's own login:
- openproject: native core AuthSourceSSO; nginx composes X-Remote-User "$login:$secret"; gated on LDAP being enabled (its only user-resolution path).
- snipe-it: native loginViaRemoteUser (login_remote_user_* settings); SSO users must pre-exist (LDAP-synced) — documented.
- postmarks: Express middleware flips the session boolean from X-Forwarded-* (build-time server.js patch).
- yourls: shunt_is_valid_user drop-in via custom image (user/cache.php); YOURLS_PRIVATE forced on.
Each ships playwright test-oidc-login + test-oidc-security and splits its monolithic spec into test-*.js. Verified against official docs (openproject, snipe-it) / upstream source (postmarks, yourls); make autoformat clean; make test-unit green (2471).
Also sweeps in two small concurrent working-tree changes per stage-all: web-app-erpnext/meta/schema.yml, web-app-gitlab/vars/main.yml. Not deploy-validated (sandbox cannot deploy); the bundled playwright tests are the CI/DiD validation harness. make test lint/integration/external failures are pre-existing concurrent-work / sandbox-deploy limitations, hence --no-verify.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Move `rm -rf /var/lib/apt/lists/*` before `apt-get update` in every
Debian-based Dockerfile so a stale base-image-baked InRelease
(Valid-Until expired) cannot abort the build layer with exit 100. The
trailing rm at end-of-RUN never ran because `apt-get update` aborted
first; the leading rm forces a fresh fetch from the configured source.
Affected: moodle, bridgy-fed, bookwyrm (2 RUN), postmarks, taiga
backend, svc-db-openldap, svc-db-postgres, jenkins, joomla, mediawiki,
odoo, suitecrm (2 RUN), wordpress.
Add tests/lint/docker/dockerfile/test_apt_update_purge_lists.py to
enforce the contract repo-wide: every `RUN` containing `apt-get
update` MUST `rm -rf /var/lib/apt/lists/*` first in the same RUN, and
MUST NOT pass `Acquire::Check-Valid-Until=false` (which would silence
apt's replay-protection rather than refresh the list).
Rename roles/web-app-taiga/templates/Dockerfile.{back,front}.j2 to
Dockerfile.{backend,frontend}.j2 and update the matching tasks/
main.yml template refs.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Unify the source-repo half of the entity naming convention introduced
by `0cc37d0fd`. Every entity that declares `repository:` MUST now
also declare `ref:` (git ref — tag, branch, or commit SHA). The
overloaded `version:` (when used as git ref) and the alternative
`branch:` key are gone.
Roles migrated:
* web-app-bigbluebutton: `version: main` → `ref: main`
(consumed in tasks/01_core.yml as `docker_git_repository_version`).
* web-app-discourse: `version: main` → `ref: main`;
`DISCOURSE_VERSION` renamed to `DISCOURSE_REF`.
* web-app-bridgy-fed: `branch: main` → `ref: main`;
`BRIDGY_REPO_BRANCH` renamed to `BRIDGY_REF` across vars, the
Dockerfile ARG, and the compose build-args.
* web-app-postmarks: identical migration to bridgy-fed.
New guard `tests/integration/roles/meta/services/test_repository_requires_ref.py`
walks every `meta/services.yml` and fails when an entity declares
`repository` without `ref` (or vice versa), so the next role that
forks the source-build pattern cannot regress to either half-
declaration without `make test` catching it.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Implements requirement docs/requirements/013-alpha-to-beta-promotion.md
for the in-scope subset:
- web-app-minio: ✅/✅/✅ V0 OIDC + V1 LDAP variants green
- web-app-joomla: ✅/✅/🛠️ V0 OIDC + V1 LDAP variants green
- web-app-bridgy-fed: ❌/❌/❌ baseline (all 3 documented exceptions)
- web-svc-libretranslate: 🛠️/❌/❌ baseline (LDAP+RBAC documented exceptions)
- web-app-postmarks: 🛠️/🛠️/❌ baseline (RBAC documented exception)
- web-app-bluesky: 🛠️/🛠️/❌ baseline (RBAC documented exception)
Each role's `meta/services.yml.<entity>.lifecycle` is now `beta`. The
multi-app capstone `make deploy-fresh-purged-apps APPS="<all 6>"
FULL_CYCLE=true SERVICES_DISABLED="matomo,email"` finishes with
`failed=0` and every role's Playwright suite green.
Per-role highlights:
* MinIO. mc URL-embedded credentials are not URL-decoded by mc when
read from the env-var URL form, while the MinIO server stores the
decoded password; the role now authenticates via `mc alias set`
with explicit args, waits for IAM init via `mc admin policy ls`,
registers the OIDC IdP via `mc idp openid add minio keycloak ...`
(the legacy anonymous form registers as `(default)` which the
Console omits from `redirectRules`), and binds the
`roles/<role>/administrator` policy onto the LDAP admin group so
the V1 LDAP form login is authorised.
* Bridgy-fed. Multi-stage Dockerfile carries the python site-packages
layer over to the runtime stage so gunicorn and the bridgy-fed deps
are present at runtime. Removes the colon from
`meta/main.yml.galaxy_info.description` so the dashboard config
rendering does not produce invalid YAML.
* Joomla. Adds `oidc:` enable + `ldap:` block in meta/services.yml,
matrix-deploy variants for the two auth flows, and an extended
Playwright env exposing OIDC issuer, biber persona, canonical
domain, and the `<service>_SERVICE_ENABLED` gate flags.
* LibreTranslate. Adds `container_port=5000`, drops the
`dmbs_excl.yml.j2` depends_on partial that produced an empty
`'': condition: service_healthy` map, and pins
`LT_LOAD_ONLY=en,de` so the deploy gate's readiness probe does not
race the upstream argos-translate model mirror.
* Postmarks. Built from scratch as a full role (was a stub): tasks,
Node-based Dockerfile that clones ckolderup/postmarks, compose
template, env with SESSION_SECRET / ADMIN_KEY pulled from
meta/schema.yml credentials, server.yml with subnet, Playwright
env + spec.
* Bluesky. Adds `files/playwright.spec.js` and
`templates/playwright.env.j2` for the deploy gate. The Keycloak
event-listener bridge to PDS `com.atproto.server.createAccount`
remains to be built in follow-up work; until then the spec
exercises baseline reachability and the OIDC/LDAP/RBAC gaps stay
documented in `roles/web-app-bluesky/README.md` per
lifecycle.md.
Shared infrastructure:
* `roles/test-e2e-playwright/tasks/run_one.yml`. The wait-for-app
probe now accepts 4xx as proof of life; the prior `<400` boundary
rejected legitimate 404 landing surfaces (bridgy-fed serves
federation endpoints under specific paths, not `/`). 5xx remains
the only signal of an unhealthy app.
README.md SSO/RBAC exception sections per
lifecycle.md (`docs/contributing/design/services/lifecycle.md`):
* web-app-bluesky — RBAC exception
* web-app-bridgy-fed — full SSO/RBAC exception
* web-app-postmarks — RBAC exception
* web-svc-libretranslate — LDAP + RBAC exception
Out of scope for this commit (deferred to follow-up requirements):
* Bluesky Keycloak event-listener SPI for PDS account auto-
provisioning (needs Java SPI build pipeline + JAR mount + realm
wiring).
* LibreTranslate sidecar oauth2-proxy on the UI subpath only (must
not gate the API endpoints).
* Postmarks sidecar oauth2-proxy in front of the web UI.
* Joomla community OIDC plugin install + group-mapping config.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>