smoke-containers: pull base images from the in-instance registry mirror (CI resilience + sovereignty) #137
Etiketter
Inga etiketter
area/backups
area/ci
area/control-panel
area/identity
area/infra
area/observability
area/payments
area/security
area/storage
area/web
blocked
needs-info
needs-triage
ready-for-implementation
type
bug
type
chore
type
docs
type
epic
type
feature
type
task
wontfix
Ingen milstolpe
Inget projekt
Inga tilldelade
1 deltagare
Notiser
Förfallodatum
Inget förfallodatum satt.
Beroenden
Inga beroenden satta
Referens
bitborg/bitborg-infra#137
Läser in…
Hänvisa till i nytt ärende
Ingen beskrivning angiven.
Ta bort grenen "%!s()"
Borttagning av en gren är permanent. Även om den borttagna grenen kan fortsätta existera en kort tid innan den faktiskt tas bort, kan det INTE ångras i de flesta fall. Vill du fortsätta?
Severity: MEDIUM (CI reliability + sovereignty). Found when PR #136's
smoke-containersjob failed on a transientcodeberg.org504 while pullingforgejo:16.0.0.Problem
scripts/smoke-containers.pypulls base images live from external registries (codeberg.org, docker.io) on every CI run. So:We already run a
registry-mirrorrole (ADR 0023) thatskopeo copys pinned images into the Forgejo registry (git.gitborg.se/bitborg/<name>:<tag>), but it currently mirrors only Renovate, andsmoke-containers.pyexplicitly skipsgit.gitborg.se/…images as "not pullable in CI".Fix
registry_mirror_images(pinned, in lockstep with the consuming roles' tags).podman pull git.gitborg.se/bitborg/<name>:<tag>. Either mark those org packages public (base images are public upstream anyway → anonymous pull) or add a scopedpodman loginin the CI workflow. Until this lands, mirror-first simply falls back to upstream (so step 2's retry is what fixes the flake now).Rollout
site.ymlapply → mirror timer populates the 4 packages.Refs: PR #136 (the flake),
registry-mirrorrole, ADR 0023, smoke #104.Implementation status
podman login git.gitborg.sebefore smoke, non-fatal.Operator steps to activate (needs prod / out-of-band)
pnpm ansible:checkpasses;registry_mirror_imageshas 5 entries on main.Anonymous pull is off (
git.gitborg.se/v2/→ 401) and thegitborgorg must stay private, hence the login rather than public packages. Until 1–3 are done, smoke keeps pulling upstream (already resilient via the #138 retry).Step 1 done + verified (applied 2026-07-19)
site.yml --tags registry-mirror,runner-controllerapplied; health-gate green. The mirror now holds all four base images (pushed bygitborg-ci, verified via the packages API):git.gitborg.se/gitborg/forgejo:16.0.0git.gitborg.se/gitborg/postgres:17.10-trixiegit.gitborg.se/gitborg/caddy:2.11.4-alpinegit.gitborg.se/gitborg/kanidm:1.10.4Both code PRs are merged: #138 (mirror-first pull + fallback + retry + transient-SKIP) and #139 (best-effort CI login).
Step 2 — remaining (only you can do this part)
The CI login needs a read-only PAT on the
gitborg-ciservice account — I can't mint another account's credential. Once it exists:After that, the smoke job authenticates and pulls the base images from the mirror (
[mirror]) instead of upstream. Until then it falls back to upstream (already resilient via retry + transient-SKIP).When you've set the secret, ping me and I'll confirm a smoke run shows
[mirror]. This issue stays open until then.Done — closing.
Both steps complete and verified:
Step 1 (applied 2026-07-19): the four base images are mirrored into the Forgejo registry (
bitborg/{forgejo:16.0.0,postgres:17.10-trixie,caddy:2.11.4-alpine,kanidm:1.10.4}), verified via the packages API.Step 2:
read:packagePAT minted ongitborg-bot(least-privilege catch-all;gitborg-cistays isolated to the deploy path), via an admin bot PAT — not a personal account.GET /v2/gitborg/forgejo/manifests/16.0.0asgitborg-botreturned 200 → the credential + org package-read both work.REGISTRY_READ_TOKENset as the repo Actions secret.ci.ymllogs in asgitborg-bot.Code merged along the way: #138 (mirror-first pull + fallback + retry + transient-SKIP), #139 (best-effort login), #140 (login user → gitborg-bot).
Net: the smoke now pulls base images from the in-instance mirror, with upstream fallback + retry + transient-SKIP as the safety net — external-registry outages can no longer fail CI, and nothing is fetched from outside the instance on the happy path. The live
[mirror]label will show on the next infra PR's smoke run.