Use shared artifacts at cache boundaries - #267
Conversation
There was a problem hiding this comment.
Pull request overview
This PR standardizes cached and newly stored package file metadata by representing artifacts with a shared artifacts.Artifact type at cache boundaries, while keeping the stored SHA-256 hex digest format unchanged for ETags and verification.
Changes:
- Refactors
CacheResultto carry anartifacts.Artifact(digest/size/filename/media type) instead of separate fields, updating serving and mirroring logic accordingly. - Validates and converts cached artifact database rows into
artifacts.Artifactat the database boundary (GetCachedArtifact). - Updates tests and adds coverage for malformed cached metadata and malformed storage digests; adds new module dependencies.
Reviewed changes
Copilot reviewed 9 out of 10 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| internal/mirror/mirror.go | Uses shared artifact size metadata for mirror accounting. |
| internal/handler/handler.go | Moves cache/fetch paths to artifacts.Artifact for size/ETag/media type and DB updates. |
| internal/handler/handler_test.go | Updates tests to assert artifact metadata and adds malformed-metadata cases. |
| internal/handler/download_test.go | Updates seeded cached artifact hashes to use encoded digest. |
| internal/handler/container_test.go | Updates ETag assertions to use encoded digest. |
| internal/database/types.go | Changes cached-artifact shape to embed artifacts.Artifact. |
| internal/database/queries.go | Converts/validates cached artifact rows into artifacts.Artifact. |
| internal/database/database_test.go | Updates cached-artifact tests and adds row conversion/validation unit tests. |
| go.mod | Adds github.com/git-pkgs/artifacts and github.com/opencontainers/go-digest. |
| go.sum | Adds checksums for the new dependencies. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| if !row.ContentHash.Valid || row.ContentHash.String == "" { | ||
| return nil, fmt.Errorf("cached artifact content hash is missing") | ||
| } | ||
| if !row.Size.Valid { | ||
| return nil, fmt.Errorf("cached artifact size is missing") | ||
| } |
| tracker.bytes.Add(result.Artifact.Size) | ||
| m.logger.Info("mirrored", |
Construct artifacts.Artifact from the row without validation so a malformed content hash reaches newIntegrityChecks in checkCache, which clears the row and treats the request as a miss. Erroring at the DB boundary instead surfaced a 500 and left the bad row in place.
36b864f to
8aaf5e8
Compare
Construct the shared artifact struct from trusted storage output as a literal, after the hash-mismatch and scanner paths that delete failed downloads, so no path between Store and updateCacheDB can leave bytes in storage without a database row.
There was a problem hiding this comment.
🟡 Changes recommended
The cached-artifact row conversion can construct an invalid non-empty digest value when content_hash is NULL/empty, which should be corrected before merge.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
- Files reviewed: 14/14 changed files
- Comments generated: 1
- Review effort level: Lite
| func (row cachedArtifactRow) artifact(versionPURL, filename string) *CachedArtifact { | ||
| return &CachedArtifact{ | ||
| Ecosystem: row.Ecosystem, | ||
| StoragePath: row.StoragePath, | ||
| Integrity: row.Integrity, | ||
| Artifact: artifacts.Artifact{ | ||
| PURL: versionPURL, | ||
| Digest: digest.Digest("sha256:" + row.ContentHash.String), | ||
| Size: row.Size.Int64, | ||
| Filename: filename, | ||
| MediaType: row.ContentType.String, | ||
| }, | ||
| } | ||
| } |
Resolves the conflict in proxyMetadataStream: keep the acceptEncoding parameter from this branch and the r.Method request from main (git-pkgs#267).
Uses
artifacts.Artifactfor cached and newly stored package files. Cache rows are converted and validated at the database boundary while the stored hexadecimal SHA-256 remains unchanged. Response ETags and cache verification continue using the encoded digest, and mirror accounting reads shared size metadata.