ci: multi-arch-safe php.net guard and emergency workflow (no platform change)

- scripts/image-label-amd64.sh: index-safe read of the amd64 image's labels
  (OCI index with attestations, Docker manifest list, single manifest).
- scripts/php-emergency-guard.sh: used by both build-push.yaml guard sites;
  same decisions as the old inline step on single-platform images, but FAILS
  CLOSED when the labels cannot be read (only "tag not found" passes).
- lsphp-source-emergency.yaml: push by digest + assemble (copy of HMB
  assemble-multiarch-index.sh); optional arm64; refuses to replace a
  multi-arch production tag with amd64-only unless allow_amd64_only.
- Tests wired into Shell-Checks; main build matrix platforms unchanged.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0185ukXjXyosSkunDsdWz3mb
This commit is contained in:
shadowdaoandClaude Sonnet 5.5 committed 2026-11-11 17:22:24 -08:00
1 parent 4b35869477
commit 8a6a6d7b44
8 files changed
+565 -24

No files matched your search

+44
View File
@@ -0,0 +1,44 @@
#!/usr/bin/env bash
## php-emergency-guard.sh REF NEW_PHP
##
## "Do not roll back a newer php.net emergency image." REF is the published
## :phpNN tag a normal build is about to overwrite; NEW_PHP is the PHP version
## the normal build packages. Exit 0 = go ahead, 1 = refuse (or cannot tell).
##
## Decision (same predicate as the old inline step, evaluated on the amd64
## image only, so it is correct for a single-platform image AND a multi-arch
## index):
## REF does not exist yet (registry "not found") -> proceed (nothing to protect)
## labels read, source != php.net -> proceed
## labels read, source = php.net, cur == new -> proceed
## labels read, source = php.net, cur > new (sort -V) -> REFUSE
## labels read, source = php.net, cur < new -> proceed
## labels absent (older image without them) -> proceed (as before)
## ANYTHING ELSE (registry/auth/network error, malformed manifest, index
## without exactly one linux/amd64 image, non-amd64 config) -> REFUSE
## (FAIL CLOSED; the old step failed open and silently disabled the guard).
## Env: LABEL_SCRIPT (tests), IMAGETOOLS passed through.
set -euo pipefail
ref=${1:?usage: php-emergency-guard.sh REF NEW_PHP}
new=${2-}
here=$(cd "$(dirname "$0")" && pwd)
labeler=${LABEL_SCRIPT:-$here/image-label-amd64.sh}
rc=0
out=$("$labeler" "$ref" org.whp.lsphp-source org.whp.php-version) || rc=$?
if [ "$rc" -eq 3 ]; then
echo "published $ref: not found (first build); this build: packaged $new. Nothing to protect."
exit 0
fi
if [ "$rc" -ne 0 ]; then
echo "::error::cannot read the php.net-emergency labels of the amd64 image behind $ref (rc=$rc). Refusing to overwrite it blind (fail closed). Retry the run; if it persists check registry access and the manifest."
exit 1
fi
src=$(printf '%s\n' "$out" | sed -n 1p)
cur=$(printf '%s\n' "$out" | sed -n 2p)
echo "published $ref (amd64): source=${src:-?} php=${cur:-?}; this build: packaged $new"
if [ "$src" = "php.net" ] && [ "$cur" != "$new" ] && [ "$(printf '%s\n%s\n' "$cur" "$new" | sort -V | tail -n1)" = "$cur" ]; then
echo "::error::$ref is a php.net emergency build of PHP $cur; LiteSpeed still ships $new. Not overwriting it with an older PHP. Re-run lsphp-source-emergency.yaml for a newer fix, or wait for LiteSpeed."
exit 1
fi
exit 0