chore: Propagate the Docker Hub login to the eleven app repositories #42
Labels
No labels
priority/P0
priority/P1
priority/P2
priority/P3
size/L
size/M
size/S
size/XL
size/XS
state/done
state/in-progress
state/in-review
state/needs-refinement
state/ready
type/bug
type/chore
type/feature
type/refactor
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
amtronics/platform-actions#42
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Context
templates/release.ymlgained a Docker Hub login (#37, PR #41) so base-image pulls stopbeing anonymous. The template is copied into each application rather than called, so
that change reaches a repository only when someone edits its workflow. Eleven repositories
carry a copy that builds images, and none of them authenticates:
Until each is updated, the fleet keeps sharing one anonymous per-IP pull limit — which is
the condition that produces
toomanyrequestson a build unrelated to whatever consumed thequota.
Scope
docker login docker.iostep to thepublishjob of eachrepository listed above.
the runner's own
container:image pulls, which are host-side(
amtronics/infrastructure-vps#395).Acceptance criteria
release.ymlis read, then thepublishjob logs in todocker.iobefore building.Notes
One pull request per repository, not one sweeping change: these are eleven independent
repositories with their own review and release cycles, and a single change touching all of
them could not be reviewed meaningfully or reverted selectively.
Copy the step verbatim from the template rather than retyping it. The guard matters — a
missing secret must warn rather than fail — and
docker/login-actionis the wrong tool hereprecisely because it fails on an empty password.
Worth checking per repository rather than assuming: a couple of these build from a
Dockerfilewhose base image is already mirrored, in which case the step is harmless butpointless, and worth skipping with a note.
Starting this. First repository done, and two findings that change what the remaining ten involve.
ahmad/portfolio→ PR ahmad/portfolio#76. The step is byte-identical to the template (compared as parsed YAML, not by eye), and I drove itsrun:body against a stubdockeron an emptyPATH: neither secret set → warns, exits 0,dockernever invoked; only the user set → same; both set →docker login docker.io -u … --password-stdin. Neutering theifmakes the unset case calldocker loginwith empty credentials, so the guard is load-bearing rather than decoration.Finding 1 — none of the eleven is already mirrored, so the "harmless but pointless" exemption in the issue body does not apply to any of them. I surveyed all eleven. Four parameterise their bases, which looks like the mirrored case:
Those defaults are digest-pinned Docker Hub tags, not fleet-registry references. Parameterised is not mirrored. All eleven genuinely need the step, and none should be skipped.
Finding 2, for
amtronics/infrastructure-vps#395rather than for this issue. Those same three repositories already have the seam that mirroring needs: because the base is anARG, pointing a build at a mirrored image is abuild-args:line in the workflow, with no Dockerfile change and nothing to review in the image definition. The other eight hardcode theirFROMand would need editing. That is worth knowing before #395 picks an approach, since it makes three repositories nearly free and eight not.Survey of the remaining ten, so the rest of this issue is a known quantity rather than a discovery each time. None currently authenticates:
ahmad/expironode:22.23.2-alpine,nginx:1.27-alpineahmad/imamahnode:22-alpine,nginx:alpineahmad/launchpad${NODE_IMAGE},${NGINX_IMAGE}ahmad/tripnode:22-alpine,nginx:alpinebayan/bayan-webnode:24-bookworm-slim@sha256:…,nginxinc/nginx-unprivileged:1.29-alpine@sha256:…bayan/kidpointsoven/bun:1.3.14-alpine,nginx:1.27-alpinebayan/stemnode:24-alpine,nginx:1.29-alpinesuhba/khitta${NODE_IMAGE}suhba/suhba-docspython:3.12-slim,nginx:1.27-alpinesuhba/suhba-webnode:24-bookworm-slim@sha256:…,nginxinc/nginx-unprivileged:1.29-alpine@sha256:…Note
bayan/kidpointspulls fromoven/bunandsuhba/suhba-docsfrompython, so this is not only alibrary/nodeconcern — the per-IP cap covers all of them.One caveat on urgency, since this issue reads like the answer to what the fleet is currently suffering. It is not. Today's failures across
ahmad/expiroareauth.docker.io … TLS handshake timeout, a connectivity fault, anddocker logintalks to that same host — so authenticating would fail identically. This issue is real and worth finishing, but it is insurance againsttoomanyrequests, a condition the fleet has not hit today. The thing actually blocking merges is #395.Ten of eleven done. Recording where this stands and why the eleventh is deliberately not open yet.
Merged (9):
ahmad/portfolio#76,ahmad/launchpad#87,ahmad/trip#129,suhba/khitta#53,Bayan/stem#10,Bayan/kidpoints#208,suhba/suhba-docs#9,Bayan/bayan-web#29,suhba/suhba-web#42.In review:
ahmad/imamah#153(green, ready).Not opened:
ahmad/expiro.Why expiro is held, and it is not only the red
imagecheck.ahmad/expiro#30— open, awaiting a human reviewer and a published-port decision — edits.forgejo/workflows/release.yml, which is exactly the file this change touches:So opening the eleventh PR now guarantees a conflict with a pull request that cannot merge without a human. Sequencing it after #30 costs nothing and avoids a rebase that someone would otherwise have to resolve. The
imagecheck being red for unrelated runner reasons (infrastructure-vps#395,#390) is a second reason, not the main one.Three things this rollout established that are worth keeping past it:
The eleven repositories do not share one workflow shape.
Bayan/stem's registry login is an unnamed- uses: docker/login-action@v3where every other repo names the step, so an anchor on that name matches nothing there — silently, since a zero-match replace still succeeds. Asserting the anchor occurs exactly once before writing is what caught it.They do not share one toolchain either: pnpm (
portfolio,launchpad,bayan-web,suhba-web,imamah), npm (trip,khitta,stem), bun (kidpoints, whosevalidaterunsbun test --coverage --coverage-threshold=0.7) and uv/Python (suhba-docs, whosevalidatecannot be reproduced locally at all — it fetches a submodule SSH key from OpenBao beforemkdocs build --strict). Reading the lockfile first is not optional; using the wrong package manager wrote a stray lockfile inahmad/tripthat only agit statuscheck caught.And the per-IP cap is not a
library/nodeconcern:kidpointspullsoven/bun,suhba-docspullspython, andbayan-web/suhba-webpin their bases by digest — which fixes which image is fetched, not how, so those pulls count against the shared limit like any other.Correction, since it appeared in one of these PRs. On
suhba/suhba-web#42I claimed that asserting the login index against everybuild-pushstep was a strengthening over checking the first, because that repository builds two images. It is not: the index list comes fromenumerate, so it is ascending andbuilds[0]ismin(builds). The forms are equivalent and the weaker one was never broken. Corrected on that PR.Fleet-wide verification, run against every repository's
mainrather than against the pull requests — the property this issue actually asserts, and the one a per-PR review cannot establish.identicalcompares the parsedLog in to Docker Hubstep object againsttemplates/release.ymlonplatform-actions/main;buildslists everybuild-pushindex in the same job. Ten of eleven carry the corrected step — the one including platform-actions#50's fix, so no repository inherited the version that failed a release on a rejected token.The two rows that differ from the pattern are both explained and both correct:
suhba/suhba-docssits at 7 because itspublishfetches a submodule key and initialises submodules first, andsuhba/suhba-webhas two builds because it also publishes a mail relay.ahmad/expirois the only one outstanding, and it is waiting on a person, not on this issue.ahmad/expiro#30is open, needs a human reviewer and a published-port decision, and edits the same.forgejo/workflows/release.ymlthis change touches. Opening the eleventh PR before it lands would put a conflict on a branch nobody can merge. Itsimagecheck is also red for unrelated runner reasons (amtronics/infrastructure-vps#395,#390), but the file collision is the binding constraint.So this issue is complete except for one repository, and that repository is blocked behind a decision only the maintainer can make. I have not marked it done.