fix to artifact diff. add missing file

This commit is contained in:
Evan Jarrett
2026-05-04 23:18:40 -05:00
parent e1483f7aa5
commit 419d05057e
5 changed files with 103 additions and 26 deletions
+33
View File
@@ -1489,6 +1489,39 @@ func UpdateFirehoseCursor(db DBTX, cursor int64) error {
return err
}
// GetChildManifestPlatform returns the platform info for a manifest that is
// referenced as a child of a manifest list. Returns nil if the digest is not
// a child of any manifest list (i.e., it's a top-level single-arch manifest).
// Used by the diff handler to match architectures when comparing a platform
// child digest against a manifest list (or another child).
func GetChildManifestPlatform(db DBTX, did, repository, digest string) (*PlatformInfo, error) {
var p PlatformInfo
var arch, os, variant, osVersion sql.NullString
err := db.QueryRow(`
SELECT
COALESCE(mr.platform_os, ''),
COALESCE(mr.platform_architecture, ''),
COALESCE(mr.platform_variant, ''),
COALESCE(mr.platform_os_version, '')
FROM manifest_references mr
JOIN manifests m ON mr.manifest_id = m.id
WHERE m.did = ? AND m.repository = ? AND mr.digest = ?
LIMIT 1
`, did, repository, digest).Scan(&os, &arch, &variant, &osVersion)
if err != nil {
if err == sql.ErrNoRows {
return nil, nil
}
return nil, err
}
p.OS = os.String
p.Architecture = arch.String
p.Variant = variant.String
p.OSVersion = osVersion.String
p.Digest = digest
return &p, nil
}
// IsManifestReferenced checks if a manifest digest is referenced as a child of
// any manifest list for the given user. Used to protect manifest list children
// from auto-removal (they are untagged but still needed by their parent list).
+56 -22
View File
@@ -333,6 +333,26 @@ func (h *ManifestDiffHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
fromPlatformDigest := ""
toPlatformDigest := ""
// platKey returns "os/arch[/variant]" for a platform.
platKey := func(os, arch, variant string) string {
k := os + "/" + arch
if variant != "" {
k += "/" + variant
}
return k
}
// pickPlatformChild returns the child digest from a manifest list whose
// platform matches the given key. Returns "" if no match.
pickPlatformChild := func(m *db.ManifestWithMetadata, key string) string {
for _, p := range m.Platforms {
if platKey(p.OS, p.Architecture, p.Variant) == key {
return p.Digest
}
}
return ""
}
if isMultiArch {
// Build intersection of platforms
for _, fp := range fromManifest.Platforms {
@@ -348,33 +368,47 @@ func (h *ManifestDiffHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
selectedPlatform = r.URL.Query().Get("platform")
if len(commonPlatforms) > 0 {
if selectedPlatform == "" {
selectedPlatform = commonPlatforms[0].OS + "/" + commonPlatforms[0].Architecture
if commonPlatforms[0].Variant != "" {
selectedPlatform += "/" + commonPlatforms[0].Variant
}
selectedPlatform = platKey(commonPlatforms[0].OS, commonPlatforms[0].Architecture, commonPlatforms[0].Variant)
}
// Find matching platform digests
for _, fp := range fromManifest.Platforms {
platKey := fp.OS + "/" + fp.Architecture
if fp.Variant != "" {
platKey += "/" + fp.Variant
}
if platKey == selectedPlatform {
fromPlatformDigest = fp.Digest
break
}
}
for _, tp := range toManifest.Platforms {
platKey := tp.OS + "/" + tp.Architecture
if tp.Variant != "" {
platKey += "/" + tp.Variant
}
if platKey == selectedPlatform {
toPlatformDigest = tp.Digest
fromPlatformDigest = pickPlatformChild(fromManifest, selectedPlatform)
toPlatformDigest = pickPlatformChild(toManifest, selectedPlatform)
}
} else if fromManifest.IsManifestList != toManifest.IsManifestList {
// Mixed: one side is a manifest list, the other is a platform child.
// Match them by looking up the single-arch side's platform via its
// parent manifest_references row and picking the matching child from
// the manifest list side.
var listSide *db.ManifestWithMetadata
var childDigest string
if fromManifest.IsManifestList {
listSide = fromManifest
childDigest = toDigest
} else {
listSide = toManifest
childDigest = fromDigest
}
plat, _ := db.GetChildManifestPlatform(h.ReadOnlyDB, owner.DID, repo, childDigest)
var listChildDigest string
if plat != nil {
listChildDigest = pickPlatformChild(listSide, platKey(plat.OS, plat.Architecture, plat.Variant))
}
// Fallback: if we couldn't determine the platform (or no match),
// default to the first non-attestation child of the manifest list so
// the diff at least shows real layers instead of an empty index.
if listChildDigest == "" {
for _, p := range listSide.Platforms {
if p.Digest != "" {
listChildDigest = p.Digest
break
}
}
}
if fromManifest.IsManifestList {
fromPlatformDigest = listChildDigest
} else {
toPlatformDigest = listChildDigest
}
}
// Fetch layer/vuln data in parallel
File diff suppressed because one or more lines are too long
+2 -3
View File
@@ -293,11 +293,10 @@ function initTabController() {
const content = document.getElementById('tag-content');
const selector = document.getElementById('tag-selector');
if (!content || !selector || !to) return;
const fromDigest = content.dataset.digest;
const currentTag = selector.value;
if (!fromDigest || to === currentTag) return;
if (!currentTag || to === currentTag) return;
window.location.href = '/diff/' + content.dataset.owner + '/' + content.dataset.repo +
'?from=' + encodeURIComponent(fromDigest) + '&to=' + encodeURIComponent(to);
'?from=' + encodeURIComponent(currentTag) + '&to=' + encodeURIComponent(to);
};
window.switchRepoTab = function(tabId) {