fix(oci): parse feature refs with both a tag and a digest (name:tag@digest)#131
Merged
Conversation
…igest) `parse_name_and_tag` handled `name:tag` and `name@digest` separately but not the combined `name:tag@digest` form. For a feature ref like `ghcr.io/devcontainers/features/git:1@sha256:DIGEST`, it split on `@`, kept the whole `git:1` as the name, and produced repository `devcontainers/features/git:1` — so the manifest URL became `https://ghcr.io/v2/devcontainers/features/git:1/manifests/sha256:DIGEST`, which 404s. Per the OCI distribution spec, when both a tag and a digest are present the digest is authoritative and the tag is informational. Strip the tag from the name portion when a digest follows, so the repository path is `devcontainers/features/git` and the manifest is fetched by digest. Surfaced by the `examples/features/oci-digest-pin` canary (scenario 2: `read-configuration --include-features-configuration` over a digest-pinned feature), which failed to resolve the manifest. Also fixes that canary's scenario 2 to pass `--config` explicitly (the config lives at the workspace root as `devcontainer.json`, not a spec discovery location), matching scenario 3. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.
Summary
parse_name_and_taghandledname:tagandname@digestseparately but not the combinedname:tag@digestform. For a feature ref likeghcr.io/devcontainers/features/git:1@sha256:DIGEST, it split on@, kept the wholegit:1as the name, and produced repositorydevcontainers/features/git:1— so the manifest URL became:Per the OCI distribution spec, when both a tag and a digest are present the digest is authoritative and the tag is informational. The fix strips the tag from the name portion when a digest follows, so the repository path is
devcontainers/features/gitand the manifest is fetched by digest:How it was found
The
examples/features/oci-digest-pincanary (scenario 2:read-configuration --include-features-configurationover a digest-pinned feature) failed to resolve the manifest. After the fix,git:1@sha256:...resolves and installs correctly (git version 2.54.0).Changes
crates/core/src/registry_parser.rs: strip the tag from the name when a digest is present; new unit tests (test_parse_name_and_tag_digest_forms,test_parse_registry_reference_tag_and_digest).examples/features/oci-digest-pin/exec.sh: scenario 2 now passes--configexplicitly (the config lives at the workspace root asdevcontainer.json, not a spec discovery location), matching scenario 3.Testing
cargo fmt/clippyclean.oci-digest-pincanary passes end-to-end against ghcr.io.🤖 Generated with Claude Code