Skip to content

Fix About-page version check broken by OCI image index (0.22.4)#46

Merged
PeterRounce merged 2 commits into
mainfrom
claude/fix-version-check-oci-index
Jun 17, 2026
Merged

Fix About-page version check broken by OCI image index (0.22.4)#46
PeterRounce merged 2 commits into
mainfrom
claude/fix-version-check-oci-index

Conversation

@PeterRounce

@PeterRounce PeterRounce commented Jun 17, 2026

Copy link
Copy Markdown
Member

Problem

The About page shows Latest Version: "unable to check" and the "Update available" button never appears on any deployed hub — logged as WARN CheckLatestVersion: no config digest in manifest.

CheckLatestVersion read manifest.Config.Digest, assuming a single-platform Docker v2 manifest with a top-level config. Since CI switched to docker/build-push-action@v6 (#43, v0.22.2), buildx pushes boltcard/card:latest as an OCI image index (application/vnd.oci.image.index.v1+json) with provenance attestations on by default — a manifests[] array and no top-level config. So the digest came back empty and the check bailed out, even though the version label is present one level deeper. See #45 for the full investigation with registry evidence.

Two complementary fixes

1. Go: parse the index (forward fix — new hubs)

  • parseManifest — a plain image manifest yields the config digest; an image index / manifest list yields the linux/amd64 child manifest digest (skips the attestation-manifest entry, falls back to any non-attestation platform for arm64-only builds).
  • resolveConfigDigest — follows one index indirection (index → image manifest → config).
  • fetchManifestAccept header now advertises the OCI index / Docker manifest-list types alongside the single-image types.

2. CI: publish a single-platform manifest (rescues existing installs)

The Go fix only helps hubs already running the new code. Already-deployed hubs (<=0.22.3) still run the broken parser, so they'd never see the button offering the update that fixes them — a chicken-and-egg lockout.

The only lever over an already-running hub is what we publish to Docker Hub. Setting provenance: false on the build-push-action steps makes buildx publish a plain single-platform manifest instead of a provenance index. Verified against the live registry: Docker Hub serves a single-platform manifest (even an OCI one) to the old code's narrow Accept header with a top-level config.digest — so the old parser succeeds and the button reappears. After the first release built this way, every stuck hub can finally see and click Update.

Verification

  • New unit tests (update_test.go) cover the OCI index, plain-manifest, fallback, and error paths.
  • End-to-end against the live Docker Hub registry: CheckLatestVersion() now returns 0.22.3 (was "").
  • Registry content-negotiation probe confirms the old narrow Accept header still gets a parseable single manifest.
  • go vet, go build, and go test -race ./... all pass; ci.yml validated.

Fixes #45

🤖 Generated with Claude Code

PeterRounce and others added 2 commits June 17, 2026 13:52
CheckLatestVersion read manifest.Config.Digest, assuming a single-platform
Docker v2 manifest. Since CI moved to docker/build-push-action@v6 (PR #43),
buildx pushes boltcard/card:latest as an OCI image index (provenance
attestations on by default) — a manifests[] array with no top-level config.
The digest came back empty, logged "no config digest in manifest", and the
About page showed "Latest Version: unable to check" with the update button
permanently hidden on every deployed hub.

Add parseManifest: for a plain image manifest it returns the config digest;
for an image index / manifest list it returns the linux/amd64 image manifest
digest (skipping the attestation manifest, falling back to any non-attestation
platform). resolveConfigDigest follows one index indirection, and the manifest
fetch now advertises the index/list media types in its Accept header.

Verified end-to-end against the live registry: CheckLatestVersion() now
returns 0.22.3. Unit tests in update_test.go cover the index, plain-manifest,
fallback, and error paths.

Fixes #45

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The Go fix in this PR only helps hubs running the new code. Already-deployed
hubs (<=0.22.3) still run the broken parser, so they would never see the
button that offers the very update containing the fix — a chicken-and-egg
lockout.

The only lever over an already-running hub is what we publish to Docker Hub.
docker/build-push-action enables provenance attestations by default, which
wraps boltcard/card:latest in an OCI image index (no top-level config) that
the old parser can't read. Set provenance: false so the published tag is a
plain single-platform manifest again. Verified against the live registry:
Docker Hub serves a single-platform manifest (even an OCI one) to the old
code's narrow Accept header with a top-level config.digest, so the old parser
succeeds and the button reappears.

Applied to webproxy too for consistency. Documented the constraint in
CLAUDE.md so it isn't silently re-enabled.

Refs #45

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@PeterRounce PeterRounce merged commit a0bab9f into main Jun 17, 2026
9 checks passed
@PeterRounce PeterRounce deleted the claude/fix-version-check-oci-index branch June 17, 2026 14:01
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.

About page "Latest Version: unable to check" — update check broken by OCI image index

1 participant