Root image multi-arch (.gitea/workflows/build-push.yaml): one job on the x86 runner; amd64 (required) and arm64 (QEMU, continue-on-error, 30 min timeout) are pushed BY DIGEST to Gitea + GHCR; scripts/assemble-multiarch-index.sh (unchanged, reused) then creates :latest, :<version>, :<sha> in both registries. arm64 failure => amd64-only tags; stale arm64 never re-attached. Adds workflow_dispatch (was missing). QEMU step now platforms: arm64.
haproxy pin (Dockerfile): was 3.0.11-1+deb13u3. Debian already ships 3.0.11-1+deb13u4 (amd64 and arm64); u3 is still installable, so the build passes today but ships the superseded revision and would hard-fail once u3 leaves the archive. Now ARG HAPROXY_UPSTREAM=3.0.11 + an apt preference Pin: version 3.0.11-* so apt takes the newest Debian revision of that upstream version; the build fails unless dpkg and haproxy -v both report 3.0.11. A 3.0->3.1 / 3.0.12 bump still needs a reviewed ARG change + the haproxy -c gate.
VERSION 2026.11.2 -> 2026.11.3 so the publish does not overwrite the :2026.11.2 rollback tag.
Dockerfile needed no other arch changes (apt haproxy/certbot/socat, pip wheels, no hard-coded binaries). The existing build gate (11 unit suites + haproxy -c scenarios) runs inside the Dockerfile, so it runs for amd64 exactly as before AND for arm64 under QEMU.
amd64 rootfs diff vs main: only the haproxy binary + dpkg metadata (u3 -> u4) plus nondeterministic noise (logs, machine-id, pip cache, pyc, test tmp dirs). No other file differs.
Both platforms build; arm64 image runs haproxy -vv (3.0.11-1+deb13u4, same feature list as amd64 incl. QUIC), python imports, validate-rendered-config.py passes on arm64.
Index assembled by the real script lists amd64+arm64 for 3 tags x 2 repos; forced arm64 failure (with a stale digest supplied) yields an amd64-only index; scripts/test-assemble-multiarch-index.py 12/12.
Merge / first run
Merging triggers a publish (push to main). Merge with [skip ci] in the merge title, then run workflow_dispatch manually. Record rollback digests first (see PR comment / report).
## What
T5 of the WHP multi-arch image plan.
1. **Root image multi-arch** (`.gitea/workflows/build-push.yaml`): one job on the x86 runner; amd64 (required) and arm64 (QEMU, `continue-on-error`, 30 min timeout) are pushed BY DIGEST to Gitea + GHCR; `scripts/assemble-multiarch-index.sh` (unchanged, reused) then creates `:latest`, `:<version>`, `:<sha>` in both registries. arm64 failure => amd64-only tags; stale arm64 never re-attached. Adds `workflow_dispatch` (was missing). QEMU step now `platforms: arm64`.
2. **haproxy pin** (`Dockerfile`): was `3.0.11-1+deb13u3`. Debian already ships `3.0.11-1+deb13u4` (amd64 and arm64); u3 is still installable, so the build passes today but ships the superseded revision and would hard-fail once u3 leaves the archive. Now `ARG HAPROXY_UPSTREAM=3.0.11` + an apt preference `Pin: version 3.0.11-*` so apt takes the newest Debian revision of that upstream version; the build fails unless dpkg and `haproxy -v` both report 3.0.11. A 3.0->3.1 / 3.0.12 bump still needs a reviewed ARG change + the `haproxy -c` gate.
3. `VERSION` 2026.11.2 -> 2026.11.3 so the publish does not overwrite the `:2026.11.2` rollback tag.
Dockerfile needed no other arch changes (apt haproxy/certbot/socat, pip wheels, no hard-coded binaries). The existing build gate (11 unit suites + `haproxy -c` scenarios) runs inside the Dockerfile, so it runs for amd64 exactly as before AND for arm64 under QEMU.
## Verified locally (throwaway registry, nothing published)
- amd64 rootfs diff vs main: only the haproxy binary + dpkg metadata (u3 -> u4) plus nondeterministic noise (logs, machine-id, pip cache, pyc, test tmp dirs). No other file differs.
- Both platforms build; arm64 image runs `haproxy -vv` (3.0.11-1+deb13u4, same feature list as amd64 incl. QUIC), python imports, `validate-rendered-config.py` passes on arm64.
- Index assembled by the real script lists amd64+arm64 for 3 tags x 2 repos; forced arm64 failure (with a stale digest supplied) yields an amd64-only index; `scripts/test-assemble-multiarch-index.py` 12/12.
## Merge / first run
Merging triggers a publish (push to main). Merge with `[skip ci]` in the merge title, then run `workflow_dispatch` manually. Record rollback digests first (see PR comment / report).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_0185ukXjXyosSkunDsdWz3mb
- build-push.yaml: one job on the x86 runner; amd64 and arm64 (QEMU,
continue-on-error) are pushed by digest to Gitea+GHCR, then
scripts/assemble-multiarch-index.sh creates :latest/:<version>/:<sha>
(same template as coraza-spoa). arm64 failure publishes amd64-only; a
stale arm64 digest is never re-attached. Adds workflow_dispatch.
- Dockerfile: pin the reviewed UPSTREAM version (HAPROXY_UPSTREAM=3.0.11) via
an apt preference so the newest Debian security revision is taken
(3.0.11-1+deb13u4 today), and fail the build unless dpkg and `haproxy -v`
both report that upstream version. The exact +deb13uN pin froze the image
on the superseded u3 and would have hard-failed once u3 left the archive.
- The existing build gate (unit suites + haproxy -c) is unchanged and runs
for each platform.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0185ukXjXyosSkunDsdWz3mb
jknapp
merged commit 46ea498db3 into main2026-11-12 02:04:33 +00:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
What
T5 of the WHP multi-arch image plan.
.gitea/workflows/build-push.yaml): one job on the x86 runner; amd64 (required) and arm64 (QEMU,continue-on-error, 30 min timeout) are pushed BY DIGEST to Gitea + GHCR;scripts/assemble-multiarch-index.sh(unchanged, reused) then creates:latest,:<version>,:<sha>in both registries. arm64 failure => amd64-only tags; stale arm64 never re-attached. Addsworkflow_dispatch(was missing). QEMU step nowplatforms: arm64.Dockerfile): was3.0.11-1+deb13u3. Debian already ships3.0.11-1+deb13u4(amd64 and arm64); u3 is still installable, so the build passes today but ships the superseded revision and would hard-fail once u3 leaves the archive. NowARG HAPROXY_UPSTREAM=3.0.11+ an apt preferencePin: version 3.0.11-*so apt takes the newest Debian revision of that upstream version; the build fails unless dpkg andhaproxy -vboth report 3.0.11. A 3.0->3.1 / 3.0.12 bump still needs a reviewed ARG change + thehaproxy -cgate.VERSION2026.11.2 -> 2026.11.3 so the publish does not overwrite the:2026.11.2rollback tag.Dockerfile needed no other arch changes (apt haproxy/certbot/socat, pip wheels, no hard-coded binaries). The existing build gate (11 unit suites +
haproxy -cscenarios) runs inside the Dockerfile, so it runs for amd64 exactly as before AND for arm64 under QEMU.Verified locally (throwaway registry, nothing published)
haproxy -vv(3.0.11-1+deb13u4, same feature list as amd64 incl. QUIC), python imports,validate-rendered-config.pypasses on arm64.scripts/test-assemble-multiarch-index.py12/12.Merge / first run
Merging triggers a publish (push to main). Merge with
[skip ci]in the merge title, then runworkflow_dispatchmanually. Record rollback digests first (see PR comment / report).🤖 Generated with Claude Code
https://claude.ai/code/session_0185ukXjXyosSkunDsdWz3mb