ci: multi-arch-safe php.net guard + emergency workflow (T6) #38

Merged
jknapp merged 1 commits from fix/multiarch-safe-guards into trunk 2026-11-12 01:55:43 +00:00
Owner

Task T6 of the WHP multi-arch image plan (docs/arm64/IMAGE-PIPELINE-PLAN.md 2.2 #5/#6, 4.1, 4.4). Does NOT change the build matrix platforms:.

What

  • scripts/image-label-amd64.sh: index-safe label read of the linux/amd64 image (raw index -> amd64 child digest, attestation children ignored -> inspect child). Works for OCI index, Docker manifest list, single manifest. Exit 0 ok / 3 tag not found / 1 anything else.
  • scripts/php-emergency-guard.sh: used by BOTH guard sites in build-push.yaml. Same decisions as the old inline step on single-platform images (54-combination test vs the verbatim old predicate), but FAILS CLOSED when labels cannot be read (registry/auth/network error, malformed manifest, no/ambiguous amd64 child, non-amd64 config). Only "tag not found" (first build) and labels-absent proceed.
  • lsphp-source-emergency.yaml: push by digest + assemble with scripts/assemble-multiarch-index.sh (verbatim copy of haproxy-manager-base PR #17, with a bash test; copied because CI cannot fetch across repos). New inputs build_arm64 (default false, QEMU, continue-on-error) and allow_amd64_only (default false). Immutable :phpNN-phpnet-X.Y.Z is always created; the production tags are REFUSED if the current tag is a multi-arch index with arm64 and arm64 was not built successfully, unless allow_amd64_only=true. A stale arm64 is never reattached.
  • scripts/index-platforms.sh + tests; all wired into Shell-Checks.

Verified

Unit tests (fixtures: two-platform index + attestations, manifest list, single manifest, malformed). Real local registry:2 with buildx-built indexes (buildx 0.38.2 and 0.15.1): the OLD inline format errors on a real index ("index of untyped nil", swallowed -> guard off); new script reads the labels. Not verified: runs on the Gitea runner, real Gitea "not found" wording (matches not found|manifest unknown|name unknown|404), emergency workflow end-to-end (not dispatched), arm64 php.net source build.

Merge

Merging to trunk triggers build-push.yaml (full publish). Merge with [skip ci] in the merge title.

🤖 Generated with Claude Code

https://claude.ai/code/session_0185ukXjXyosSkunDsdWz3mb

Task T6 of the WHP multi-arch image plan (docs/arm64/IMAGE-PIPELINE-PLAN.md 2.2 #5/#6, 4.1, 4.4). Does NOT change the build matrix `platforms:`. ## What - `scripts/image-label-amd64.sh`: index-safe label read of the linux/amd64 image (raw index -> amd64 child digest, attestation children ignored -> inspect child). Works for OCI index, Docker manifest list, single manifest. Exit 0 ok / 3 tag not found / 1 anything else. - `scripts/php-emergency-guard.sh`: used by BOTH guard sites in build-push.yaml. Same decisions as the old inline step on single-platform images (54-combination test vs the verbatim old predicate), but FAILS CLOSED when labels cannot be read (registry/auth/network error, malformed manifest, no/ambiguous amd64 child, non-amd64 config). Only "tag not found" (first build) and labels-absent proceed. - `lsphp-source-emergency.yaml`: push by digest + assemble with `scripts/assemble-multiarch-index.sh` (verbatim copy of haproxy-manager-base PR #17, with a bash test; copied because CI cannot fetch across repos). New inputs `build_arm64` (default false, QEMU, continue-on-error) and `allow_amd64_only` (default false). Immutable `:phpNN-phpnet-X.Y.Z` is always created; the production tags are REFUSED if the current tag is a multi-arch index with arm64 and arm64 was not built successfully, unless `allow_amd64_only=true`. A stale arm64 is never reattached. - `scripts/index-platforms.sh` + tests; all wired into Shell-Checks. ## Verified Unit tests (fixtures: two-platform index + attestations, manifest list, single manifest, malformed). Real local registry:2 with buildx-built indexes (buildx 0.38.2 and 0.15.1): the OLD inline format errors on a real index ("index of untyped nil", swallowed -> guard off); new script reads the labels. Not verified: runs on the Gitea runner, real Gitea "not found" wording (matches `not found|manifest unknown|name unknown|404`), emergency workflow end-to-end (not dispatched), arm64 php.net source build. ## Merge Merging to trunk triggers build-push.yaml (full publish). Merge with `[skip ci]` in the merge title. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_0185ukXjXyosSkunDsdWz3mb
jknapp added 1 commit 2026-11-12 01:22:39 +00:00
- 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
jknapp merged commit adf74e2f69 into trunk 2026-11-12 01:55:43 +00:00
jknapp deleted branch fix/multiarch-safe-guards 2026-11-12 01:55:43 +00:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: cloud-hosting-platform/cloud-apache-container#38