fix(registry): drop token call for GAR, parse its nested tag shape - #6
Merged
Conversation
Every op-stack chain in the catalog (~14 of them) was failing in
versioncheck with:
decode token response: invalid character '<' looking for beginning of value
Root cause: us-docker.pkg.dev (Google Artifact Registry) does not
implement the Docker Distribution /token endpoint at all — it
302-redirects to console.cloud.google.com and the HTML lands in our
JSON decoder. Public GAR repositories don't need a bearer token in
the first place; /v2/{repo}/tags/list answers 200 directly.
GAR also doesn't return the standard {"tags": [...]} envelope. It
returns {"manifest": {digest: {"tag": [...]}}}, ignores ?n=
pagination, and dumps every digest in one (~2 MB) response.
Split the OCI client into two paths keyed on c.host:
- us-docker.pkg.dev -> fetchGARTags: no token, flatten manifest map
- everything else -> fetchStandardTags: same token+tags flow as
before (ECR Public still works)
Added httptest-based coverage for both paths, including the GAR
host-prefix normalization, ECR Public's access_token field, and
the non-200 error branch.
Re-running cmd/versioncheck against master:
- base, bob, celo, ink, mode, optimism, soneium now report real
UPDATE AVAILABLE entries instead of decode errors
- plume (ECR Public path) keeps working
Out of scope for this PR (separate items):
- ~17 Docker Hub 404s — repos were renamed/moved upstream, fix is
per-chain in the adapters
- GHCR 403 on morph/sonic/zircuit — same story (probably renamed)
- isStableTag missing -synctest/-cdfpl/-overrides suffix variants
that op-stack repos use for non-release builds
Context: curled the GAR and ECR Public token + tags endpoints by
hand to see exactly what each one returns, then split the client.
~1h including the test scaffold.
tazhate
added a commit
that referenced
this pull request
Jun 14, 2026
…ub tests Merging the GAR (#6) and Docker Hub pagination (#8) branches landed two copies of rewriteTransport and tagSet in package registry with different signatures, so the test binary stopped compiling (the merges only ever got go-built, which skips _test.go). Renamed the oci_test.go pair to ociRewriteTransport / ociTagList to clear the collision. Context: caught this during a local merge-train of the seven open PRs — go build passed after each merge but go test -count=1 failed the registry package on duplicate decls. Reconciled by hand, full suite green after.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Every op-stack chain in the catalog (~14 of them) was failing in
versioncheckwith:us-docker.pkg.dev(Google Artifact Registry) doesn't implement the Docker Distribution/tokenendpoint at all — it 302-redirects toconsole.cloud.google.comand the HTML body lands in our JSON decoder. Public GAR repos don't need a bearer token in the first place;/v2/{repo}/tags/listanswers 200 directly.GAR also doesn't return the standard
{"tags":[...]}envelope. It returns{"manifest":{digest:{"tag":[...]}}}, ignores?n=pagination, and dumps every digest in one ~2 MB response.What
Split
ociClient.LatestTagsinto two paths keyed onc.host:us-docker.pkg.devfetchGARTagsmanifestmapfetchStandardTagstags[]flowAdded
httptest-based coverage for both paths: GAR happy path, GAR host-prefix normalization, ECR Public bearer flow, ECR Publicaccess_tokenfield, and GAR non-200 error.Before / after (live run on master)
decode token responseerrorv1.xtags returned, several now flaggedUPDATE AVAILABLEOut of scope (separate PRs)
isStableTagdoesn't catch op-stack pre-release suffixes like-synctest,-cdfpl,-overridesTest plan
go test ./internal/registry/...— newoci_test.gowith 5 casesgo build ./...go run ./cmd/versioncheck— verified op-stack chains return tagsStacks well with #5 (semver-max picker) — both PRs are independent but together fix two distinct classes of bug in the same tool.