Repository navigation
Conversation
…idation on pull to ensure idempotency.
There was a problem hiding this comment.
Code Review
This pull request introduces a StatTag method to the Storage interface and its distribution implementation to verify tag existence. This new method is utilized in the pullIfNotExist function to ensure manifests are pushed when a tag is missing, even if the underlying blob is already present. The changes also include minor formatting adjustments to model file constants and updated mocks. A review comment suggested using errors.As for more robust error handling of wrapped ErrTagUnknown errors.
| if err != nil { | ||
| switch err.(type) { | ||
| case distribution.ErrTagUnknown: | ||
| return false, nil | ||
| } | ||
| return false, err | ||
| } |
There was a problem hiding this comment.
Using switch err.(type) to check for distribution.ErrTagUnknown may fail if the error is wrapped. Since the project uses wrapped errors (e.g., %w), it is safer and more idiomatic to use errors.As to check for specific error types.
| if err != nil { | |
| switch err.(type) { | |
| case distribution.ErrTagUnknown: | |
| return false, nil | |
| } | |
| return false, err | |
| } | |
| if err != nil { | |
| var tagErr distribution.ErrTagUnknown | |
| if errors.As(err, &tagErr) { | |
| return false, nil | |
| } | |
| return false, err | |
| } |
aftersnow
left a comment
There was a problem hiding this comment.
Thanks for the contribution! The fix direction is correct. A few suggestions:
Required
-
Missing digest validation on tag re-creation path: When manifest exists but tag doesn't,
io.ReadAll(reader)reads content and pushes it, but the function returns early beforevalidateDigest(). Please add validation or comment why it's safe to skip. -
No unit test coverage: The core new path (
StatManifest=true, StatTag=false) has no tests. Please add coverage.
Suggestions
-
The formatting changes in
constants.goare unrelated to the fix — consider a separate commit. -
The second commit message
feat: update disis unclear — please reword it.
aftersnow
left a comment
There was a problem hiding this comment.
Follow-up review on the current head (6125024). I reproduced #483 on today's main (f241cec) with a local registry, so the fix is still needed:
pull 1 -> Successfully pulled, `ls` shows the tag
rm 1 -> Deleted: v1
pull 2 -> Successfully pulled, but `ls` shows 0 rows (tag not recreated)
rm 2 -> Error: failed to delete manifest v1: filesystem: Path not found: .../_manifests/tags/v1
The direction of the fix (re-create the tag when the manifest blob already exists) is right. What still blocks it:
1. Digest validation is skipped on the re-tag path (pkg/backend/pull.go). When StatManifest is true and StatTag is false, the code reads the remote manifest with io.ReadAll(reader) and stores it under the tag, then returns before validateDigest runs. A corrupted or substituted response from the registry is stored and tagged without a check. Please validate the digest of body against desc.Digest before PushManifest, the same as the non-existing path does.
2. A stale tag is not refreshed. StatTag only reports existence. If the local tag exists but points to an older manifest (the remote tag moved), the pull still skips and leaves the stale tag in place. repository.Tags(ctx).Get(ctx, tag) already returns the descriptor; comparing its digest with desc.Digest and re-tagging on mismatch fixes this with no extra storage call. That would also make StatTag return the digest instead of a bool.
3. No unit test for the new branch (StatManifest=true, StatTag=false). The storage mock already has StatTag, so a table test on pullIfNotExist is cheap.
4. Unrelated reformatting of pkg/modelfile/constants.go conflicts with main today and is not part of the fix. Please drop it (or send it separately).
5. DCO fails. Both commits need a Signed-off-by line (git commit -s).
The errors.As change for distribution.ErrTagUnknown that Gemini asked for is in place.
related issue:#483
FIx:
add tag validation when pulling
Test: