Skip to content

Tell a missing arch apart from one that did not read - #282

Merged
ericmj merged 1 commit into
mainfrom
manifest-arch-reads
Jul 31, 2026
Merged

Tell a missing arch apart from one that did not read#282
ericmj merged 1 commit into
mainfrom
manifest-arch-reads

Conversation

@ericmj

@ericmj ericmj commented Jul 31, 2026

Copy link
Copy Markdown
Member

hexpm/elixir:1.16-erlang-26.2.5.15-alpine-3.21.5 is a single-arch amd64 manifest in the registry right now, not a multi-arch index, so arm64 pulls of it get an amd64 image. Both per-arch images have been present since 2025-10-09; the manifest was rewritten at 2026-07-30 02:24 without anything being built.

fetch_tag/2 returned nil both when Docker Hub said the tag was gone and when it answered 200 with a body carrying no usable image data, and get_archs/2 dropped the arch either way. One unreadable response was enough for manifest.sh to run imagetools create with a single source, which replaces the index with a copy of that one manifest. fetch_tag/2 now answers :not_found or :unreadable, and the manifest is published only once every arch has answered. A 404 still counts as absent, which is how a tag gets a manifest while its second arch is still building.

add_docker_tag/4 merged the reported archs into the existing row, so the re-publish recorded the loss as a no-op and the row still claimed both archs. manifest_mismatches/3 reads that row, so nothing looked wrong afterwards and the tag stayed broken until the next reconcile happened to replace the row. The row now takes the archs it is given, which is also what swap_docker_tags/2 already does.

The bad reads come from Docker Hub's tag API. It currently reports 1.20.2-erlang-29.0.4-debian-trixie-20260713-slim as arm64-only while the registry has both platforms — that is what reconcile writes at 01:00, and what the 02:15 check acts on by re-publishing. With this change that re-publish is still churn, but it can no longer degrade the tag.

Repairing the already-broken tag is not part of this. Both of its per-arch tags read cleanly, so a DockerManifest run rebuilds the index correctly.

hexpm/elixir:1.16-erlang-26.2.5.15-alpine-3.21.5 is a single-arch amd64
manifest in the registry as of 2026-07-30 02:24, though both per-arch
images have been there since 2025-10-09.

fetch_tag/2 answered nil both for a 404 and for a 200 whose body carried
no usable image data, and get_archs/2 dropped the arch either way, so one
unreadable response was enough for manifest.sh to run imagetools create
with a single source and rewrite the multi-arch index as a copy of it.
fetch_tag/2 now answers :not_found or :unreadable, and the manifest is
published only when every arch answered. A 404 still means the tag is
absent, which is how a manifest gets published while the second arch is
still building.

add_docker_tag/4 merged the reported archs into the row, so a manifest
that lost one still read as complete and manifest_mismatches/3 compared
against a row claiming both. That is why this survived: the re-publish
recorded the loss as a no-op and nothing looked wrong until the next
reconcile replaced the row. The row now takes the archs it is given.

Docker Hub's tag API is the source of the bad reads. It currently reports
1.20.2-erlang-29.0.4-debian-trixie-20260713-slim as arm64 only while the
registry has both platforms, which is what reconcile writes at 01:00 and
what the 02:15 check then acts on.

Repairing the broken tag is not part of this.
@ericmj
ericmj marked this pull request as ready for review July 31, 2026 00:23
@ericmj
ericmj merged commit c2773b1 into main Jul 31, 2026
4 checks passed
@ericmj
ericmj deleted the manifest-arch-reads branch July 31, 2026 00:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant