Make provenance-label readers multi-arch aware
Sync upstream and build images / sync-and-build (push) Successful in 25s

Publishing -r2 exposed this: a buildx multi-arch push stores an OCI index at
the tag, and both label readers assumed a single-arch manifest. Consequences
were a release body with 'pnpm ?' and — much worse — CI's freshness check
seeing the pinned image as permanently stale, which would have published a
new -rN revision every six hours forever.

Both readers now follow an index to a platform manifest (preferring amd64,
the deployment's arch) before reading the config blob, and the publisher
warns when an image carries no provenance labels at all. Verified against
both a multi-arch tag (0.1.1-rc.2-r2) and a single-arch one (0.1.5-rc.2):
the pinned build now reads as current, so no redundant rebuild.

Co-Authored-By: Claude Fable 5 <[email protected]>
This commit is contained in:
Miles WardandClaude Fable 5 committed 2026-09-11 12:11:25 -04:00
1 parent 400797ecac
commit 2a0c808149
2 files changed
+38 -7

No files matched your search

+21 -1
View File
@@ -36,10 +36,15 @@ const UPSTREAM = 'deepseek-ai/deepseek-harness';
const UA = 'deepseek-harness-release-bot/1.0';
const MANIFEST_ACCEPT = [
'application/vnd.oci.image.index.v1+json',
'application/vnd.docker.distribution.manifest.list.v2+json',
'application/vnd.docker.distribution.manifest.v2+json',
'application/vnd.oci.image.manifest.v1+json',
].join(',');
/** Platform preferred when a tag is a multi-arch index (the deployment's arch). */
const PREFERRED_ARCH = 'amd64';
async function gitea(method, path, body) {
const res = await fetch(`${GITEA}/api/v1${path}`, {
method,
@@ -134,14 +139,29 @@ function caveats(ver) {
async function imageFacts(tag) {
const res = await registry(`manifests/${tag}`, MANIFEST_ACCEPT);
if (!res.ok) throw new Error(`manifest ${tag}: HTTP ${res.status}`);
// The digest reported is the one `docker pull <tag>` pins — for a multi-arch
// tag that is the index, not any single platform's manifest.
const digest = res.headers.get('docker-content-digest') || '';
const manifest = await res.json();
let manifest = await res.json();
// A multi-arch tag is an index: follow it to a platform manifest, because
// only that one carries the config blob the labels live in.
if (Array.isArray(manifest.manifests)) {
const entries = manifest.manifests.filter((m) => m.platform?.os === 'linux');
const chosen = entries.find((m) => m.platform?.architecture === PREFERRED_ARCH) ?? entries[0];
if (!chosen) throw new Error(`manifest ${tag}: index has no linux platform`);
const sub = await registry(`manifests/${chosen.digest}`, MANIFEST_ACCEPT);
if (!sub.ok) throw new Error(`manifest ${tag} -> ${chosen.digest}: HTTP ${sub.status}`);
manifest = await sub.json();
}
const cfgDigest = manifest.config?.digest;
let labels = {};
if (cfgDigest) {
const blob = await registry(`blobs/${cfgDigest}`, '*/*');
if (blob.ok) labels = (await blob.json()).config?.Labels ?? {};
}
if (!labels['dev.milesward.pnpm-version']) {
console.error(`::warning::${tag}: no provenance labels found on the image config`);
}
return {
digest,
pnpm: labels['dev.milesward.pnpm-version'] || '',
+17 -6
View File
@@ -87,13 +87,24 @@ jobs:
[ "$(curl -s -o /dev/null -w '%{http_code}' -u "${{ github.repository_owner }}:${TOKEN}" \
-H "Accept: $ACCEPT" "https://${REGISTRY}/v2/${IMAGE}/manifests/$1")" = 200 ]
}
# Labels of a single-arch manifest's config blob ("pnpm|base|recipe");
# empty output (index manifests, missing labels) means "treat as stale".
# Provenance labels from a tag's image config ("pnpm|base|recipe").
# Empty output means "treat as stale". A multi-arch tag resolves to an
# index, whose first child manifest is followed to reach the config —
# without that, such a tag would look stale on every run and spam a
# new revision build every six hours.
fetch_manifest() {
curl -s -u "${{ github.repository_owner }}:${TOKEN}" -H "Accept: $ACCEPT" \
"https://${REGISTRY}/v2/${IMAGE}/manifests/$1"
}
first_digest() { printf '%s' "$1" | grep -o '"digest": *"sha256:[a-f0-9]*"' | head -1 | grep -o 'sha256:[a-f0-9]*'; }
tag_toolchain() {
MAN=$(curl -s -u "${{ github.repository_owner }}:${TOKEN}" \
-H 'Accept: application/vnd.docker.distribution.manifest.v2+json,application/vnd.oci.image.manifest.v1+json' \
"https://${REGISTRY}/v2/${IMAGE}/manifests/$1") || return 0
CFG=$(printf '%s' "$MAN" | grep -o '"digest": *"sha256:[a-f0-9]*"' | head -1 | grep -o 'sha256:[a-f0-9]*') || return 0
MAN=$(fetch_manifest "$1") || return 0
if printf '%s' "$MAN" | grep -q '"manifests"'; then
CHILD=$(first_digest "$MAN")
[ -n "$CHILD" ] || return 0
MAN=$(fetch_manifest "$CHILD") || return 0
fi
CFG=$(first_digest "$MAN") || return 0
[ -n "$CFG" ] || return 0
BLOB=$(curl -s -u "${{ github.repository_owner }}:${TOKEN}" "https://${REGISTRY}/v2/${IMAGE}/blobs/$CFG") || return 0
P=$(printf '%s' "$BLOB" | grep -o '"dev.milesward.pnpm-version":"[^"]*"' | cut -d'"' -f4 || true)