Skip to content

fix(gc): keep tag manifests' digest aliases, reap manifest meta sidecars - #950

Merged
ertime037 merged 1 commit into
getnora-io:mainfrom
jgrund:fix/gc-tag-manifest-digest-alias
Sep 3, 2026
Merged

fix(gc): keep tag manifests' digest aliases, reap manifest meta sidecars#950
ertime037 merged 1 commit into
getnora-io:mainfrom
jgrund:fix/gc-tag-manifest-digest-alias

Conversation

@jgrund

@jgrund jgrund commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

What

  • The tag-rooted GC mark walk now hashes each tag manifest's bytes and marks manifests/sha256:<digest>.json — the digest alias of the tag manifest itself — as a root, alongside the children it already marked.
  • An orphaned digest manifest now takes its .meta.json sidecar with it; the sidecar was invisible to detection on its own and leaked forever.
  • Regression test: tagged manifest + digest alias + sidecars + an untagged orphan pair; after a live GC run the alias and its sidecar survive (pull-by-digest keeps working) and the orphan pair is fully reaped.

Why

Fixes #949. Since #938 (v1.2.2), the sweep deleted manifests/sha256:<digest>.json while manifests/<tag>.json — the same bytes — survived, so every pull-by-digest of a tagged image 404'd after the first GC run while pull-by-tag kept working. For proxy-cached or seeded repos whose upstream has moved on, the deleted digest alias was unrecoverable. The OCI distribution spec requires content pullable by tag to stay pullable by digest.

Checklist

  • Tests pass (cargo test)
  • No new clippy warnings (cargo clippy -- -D warnings)
  • Updated CHANGELOG.md (if user-facing change)
  • New registry? See CONTRIBUTING.md checklist

The tag-rooted mark walk (getnora-io#938) marked a tag manifest's children (arch
manifests, config, layer blobs) but not the digest-named file of the tag
manifest itself. The sweep then deleted manifests/sha256:<digest>.json
while manifests/<tag>.json — the same bytes — survived, so pull-by-digest
404'd while pull-by-tag worked. The walk now hashes each tag manifest's
bytes and marks the sha256:<digest>.json alias as a root, per the OCI
distribution spec requirement that content pullable by tag stays
pullable by digest.

Also reap the .meta.json sidecar together with an orphaned digest
manifest; it was invisible to detection on its own and leaked forever.

Fixes getnora-io#949

Signed-off-by: Joe Grund <grundjoseph@gmail.com>
@jgrund
jgrund force-pushed the fix/gc-tag-manifest-digest-alias branch from ac95135 to c295b68 Compare August 31, 2026 18:18
@ertime037
ertime037 added this pull request to the merge queue Sep 3, 2026
Merged via the queue into getnora-io:main with commit a5fbbeb Sep 3, 2026
17 of 18 checks passed
@jgrund
jgrund deleted the fix/gc-tag-manifest-digest-alias branch September 3, 2026 16:50
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.

gc: tag-rooted mark walk skips the digest-named file of a tag-referenced manifest

2 participants