Skip to content

fix(registry): drop token call for GAR, parse its nested tag shape - #6

Merged
tazhate merged 1 commit into
masterfrom
fix/oci-client-gar-tokenless
Jun 14, 2026
Merged

fix(registry): drop token call for GAR, parse its nested tag shape#6
tazhate merged 1 commit into
masterfrom
fix/oci-client-gar-tokenless

Conversation

@tazhate

@tazhate tazhate commented May 28, 2026

Copy link
Copy Markdown
Owner

Why

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

us-docker.pkg.dev (Google Artifact Registry) doesn't implement the Docker Distribution /token endpoint at all — it 302-redirects to console.cloud.google.com and the HTML body lands in our JSON decoder. Public GAR repos 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.

What

Split ociClient.LatestTags into two paths keyed on c.host:

host path notes
us-docker.pkg.dev fetchGARTags no token, flatten manifest map
anything else (ECR Public, ...) fetchStandardTags unchanged token + tags[] flow

Added httptest-based coverage for both paths: GAR happy path, GAR host-prefix normalization, ECR Public bearer flow, ECR Public access_token field, and GAR non-200 error.

Before / after (live run on master)

chain before after
optimism, base, bob, celo, ink, mode, soneium, doma, fraxtal, katana, lisk, superseed, swell, unichain, worldchain, zora decode token response error real v1.x tags returned, several now flagged UPDATE AVAILABLE
plume (ECR Public) working still working — no regression

Out of scope (separate PRs)

  • ~17 Docker Hub 404s (boba-eth, core, cronos, dymension, fantom, kava, manta-pacific, metis, solana, sei, taiko, ...) — upstream repo renames, fix is per-chain in the adapters
  • GHCR 403s on morph/sonic/zircuit — same upstream-rename story (403 from GHCR usually means "doesn't exist publicly")
  • isStableTag doesn't catch op-stack pre-release suffixes like -synctest, -cdfpl, -overrides

Test plan

  • go test ./internal/registry/... — new oci_test.go with 5 cases
  • go build ./...
  • go run ./cmd/versioncheck — verified op-stack chains return tags
  • CI green

Stacks well with #5 (semver-max picker) — both PRs are independent but together fix two distinct classes of bug in the same tool.

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.
@tazhate
tazhate merged commit 351c69a into master Jun 14, 2026
0 of 9 checks passed
@tazhate
tazhate deleted the fix/oci-client-gar-tokenless branch June 14, 2026 07:18
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