Skip to content

fix(registry): paginate Docker Hub tags so newest release is found - #8

Merged
tazhate merged 1 commit into
masterfrom
fix/dockerhub-pagination
Jun 14, 2026
Merged

fix(registry): paginate Docker Hub tags so newest release is found#8
tazhate merged 1 commit into
masterfrom
fix/dockerhub-pagination

Conversation

@tazhate

@tazhate tazhate commented May 28, 2026

Copy link
Copy Markdown
Owner

Summary

internal/registry/dockerhub.go only read the first page (50 tags) of the Docker Hub tags API with ordering=last_updated. Because last_updated is not semver order, repositories with thousands of tags never surfaced their real latest release on page 1, so versioncheck reported a stale "latest".

This change follows the response next link and accumulates matching tags across pages (page_size=100) until it holds a generous surplus (~maxResults*4) or pages run out, capped at maxPages=20 to avoid unbounded crawls on giant repos. The LatestTags(ctx, policy, maxResults) signature, pattern filtering, and error behavior are unchanged. The caller still picks the semver max via registry.IsNewer, now over a much larger candidate set.

Before / After

repo before (page 1 only) after (paginated)
harmony v4.2.1 (stale) real v8.x release found
bsc 1.3.0 (stale) 1.6.x release found
klaytn stale early tag current release found

Implementation notes

  • Added Next string (json:"next") to dockerHubTagsResponse.
  • resolveDockerHubNext follows the absolute next URL as-is; relative links resolve against the current page URL.
  • ctx is checked on every page (cancellation / timeout respected).

Test plan

go build ./... and go test ./internal/registry/... are green. New tests in internal/registry/dockerhub_test.go using httptest.Server + a rewriteTransport (mirrors the oci_test pattern):

  • TestDockerHubLatestTagsPaginates: 3 pages chained via absolute hub.docker.com next URLs; asserts all pages fetched, matching tags collected from every page, non-matching tags filtered, and semver selection finds the release on the deepest page.
  • TestDockerHubLatestTagsRespectsMaxPages: infinite next chain; stops at exactly maxPages fetches.
  • TestDockerHubLatestTagsStopsAtSurplus: stops once the ~maxResults*4 surplus is collected.
  • TestDockerHubLatestTagsContextCancel: pre-cancelled context returns an error.

Docker Hub serves tags ordered by last_updated, which is not semver order.
Reading only the first page (50 tags) of repos with thousands of tags
(harmony, bsc, klaytn) hid the real latest release, so versioncheck reported a
stale "latest" (harmony saw v4.2.1 instead of v8.x, bsc 1.3.0 instead of
1.6.x).

Now follow the response "next" link with page_size=100, accumulating matching
tags across pages until a generous surplus (~maxResults*4) is held or pages run
out, capped at maxPages=20 to avoid an unbounded crawl on giant repos. The
caller still picks the semver max via IsNewer, now over a much larger candidate
set, so last_updated ordering no longer matters.

Context: I traced how only page 1 was parsed and reproduced the stale-latest
behaviour, confirmed last_updated is not semver order from the API shape, then
added pagination plus httptest-based tests (rewriteTransport) covering
multi-page collection, the surplus stop, the maxPages cap, and ctx
cancellation. Spent ~1.5h investigating and testing.
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 39469f9 into master Jun 14, 2026
0 of 9 checks passed
@tazhate
tazhate deleted the fix/dockerhub-pagination 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