Dockerfile: Go stages pinned to $BUILDPLATFORM, GOOS/GOARCH from TARGETOS/ TARGETARCH (CGO already off); amd64 rootfs/binary byte-identical to before. Workflow: one trusted x86 job, amd64 + arm64 pushed untagged by digest to both registries, arm64 continue-on-error, tag assembled by scripts/assemble-multiarch-index.sh (arm64 only from this run's successful step; otherwise amd64-only). Offline test + local e2e rehearsal script. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0185ukXjXyosSkunDsdWz3mb
112 lines
5.0 KiB
YAML
112 lines
5.0 KiB
YAML
name: Build and push coraza-spoa
|
|
run-name: ${{ gitea.actor }} pushed a change to coraza-spoa/
|
|
|
|
# Triggers only on changes to the coraza-spoa subdirectory or this workflow
|
|
# file itself — keeps the main haproxy-manager-base build and the coraza-spoa
|
|
# build independent. workflow_dispatch lets us trigger manually after bumping
|
|
# the upstream coraza-spoa version pin.
|
|
on:
|
|
push:
|
|
branches:
|
|
- main
|
|
paths:
|
|
- 'coraza-spoa/**'
|
|
- 'scripts/assemble-multiarch-index.sh'
|
|
- '.gitea/workflows/build-push-coraza.yaml'
|
|
workflow_dispatch:
|
|
|
|
# Multi-arch (linux/amd64 + linux/arm64) in ONE job on the trusted x86 runner,
|
|
# no QEMU: coraza-spoa/Dockerfile cross-compiles the Go binary
|
|
# (--platform=$BUILDPLATFORM + GOOS/GOARCH). Each platform is pushed BY DIGEST
|
|
# (untagged) to BOTH registries, then scripts/assemble-multiarch-index.sh
|
|
# creates the :latest index from those digests. The arm64 step is
|
|
# continue-on-error: if it fails, :latest is published amd64-only exactly as it
|
|
# was before multi-arch, and a previous run's arm64 is never re-attached (the
|
|
# arm64 digest is read only from THIS run's step output). Registry write
|
|
# credentials exist only on this x86 job. Template for the other WHP image
|
|
# repos: docs/arm64/IMAGE-PIPELINE-PLAN.md sections 4.1 / 4.4.
|
|
jobs:
|
|
Build-and-Push:
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 30
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
|
|
# Internal package cache (CT130 pkg-cache; canonical docs: docs/pkg-cache.md
|
|
# in cloud-apache-container). Used ONLY if it answers over TLS with our
|
|
# pinned CA; otherwise (down, unreachable, bad/expired cert) this job builds
|
|
# from the upstream repositories / default GOPROXY exactly as before. The
|
|
# build stages' base (golang:1.25) comes from the in-house registry
|
|
# (repo.anhonesthost.net, weekly digest-pinned mirror of Docker Hub -
|
|
# mirror-base-image.yaml) and the runtime base from gcr.io, not docker.io,
|
|
# so the pkg-cache registry mirror is never used here: repos + Go modules.
|
|
# The CA lives under coraza-spoa/ because that is this build's context.
|
|
- name: Probe package cache
|
|
id: pkgcache
|
|
run: |
|
|
url=""
|
|
if curl -fsS --max-time 5 --cacert coraza-spoa/keys/pkg-cache/ca.crt -o /dev/null https://192.168.1.40/; then url="https://192.168.1.40"; fi
|
|
echo "pkg-cache: repos=${url:-<unreachable: upstream>} registry-mirror=<not used: no docker.io base (base from repo.anhonesthost.net)>"
|
|
[ -n "$url" ] || echo "::warning::pkg-cache unreachable - building from upstream repositories"
|
|
echo "url=${url}" >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Set up Docker Buildx
|
|
uses: https://github.com/docker/setup-buildx-action@v3
|
|
|
|
- name: Login to Gitea
|
|
uses: docker/login-action@v3
|
|
with:
|
|
registry: repo.anhonesthost.net
|
|
username: ${{ secrets.CI_USER }}
|
|
password: ${{ secrets.CI_TOKEN }}
|
|
|
|
# Mirror to GitHub Container Registry - see build-push.yaml for the
|
|
# secret/username convention.
|
|
- name: Login to GHCR
|
|
uses: docker/login-action@v3
|
|
with:
|
|
registry: ghcr.io
|
|
username: shadowdao
|
|
password: ${{ secrets.GHCR_TOKEN }}
|
|
|
|
# amd64: required. Failure here fails the job and publishes nothing, as
|
|
# before. Pushed untagged by digest to both registries (same digest in
|
|
# each); the tag is only created by the assemble step below.
|
|
- name: Build amd64 (push by digest)
|
|
id: amd64
|
|
uses: docker/build-push-action@v6
|
|
with:
|
|
context: ./coraza-spoa
|
|
platforms: linux/amd64
|
|
build-args: |
|
|
PKG_CACHE=${{ steps.pkgcache.outputs.url }}
|
|
outputs: type=image,"name=repo.anhonesthost.net/cloud-hosting-platform/coraza-spoa,ghcr.io/shadowdao/coraza-spoa",push-by-digest=true,name-canonical=true,push=true
|
|
|
|
# arm64: best effort (cross-compiled, no emulation). Must never block or
|
|
# alter the amd64 tag.
|
|
- name: Build arm64 (push by digest)
|
|
id: arm64
|
|
continue-on-error: true
|
|
timeout-minutes: 15
|
|
uses: docker/build-push-action@v6
|
|
with:
|
|
context: ./coraza-spoa
|
|
platforms: linux/arm64
|
|
build-args: |
|
|
PKG_CACHE=${{ steps.pkgcache.outputs.url }}
|
|
outputs: type=image,"name=repo.anhonesthost.net/cloud-hosting-platform/coraza-spoa,ghcr.io/shadowdao/coraza-spoa",push-by-digest=true,name-canonical=true,push=true
|
|
|
|
- name: Assemble :latest index
|
|
env:
|
|
AMD64_DIGEST: ${{ steps.amd64.outputs.digest }}
|
|
ARM64_DIGEST: ${{ steps.arm64.outputs.digest }}
|
|
ARM64_OUTCOME: ${{ steps.arm64.outcome }}
|
|
run: |
|
|
scripts/assemble-multiarch-index.sh \
|
|
--amd64 "$AMD64_DIGEST" \
|
|
--arm64 "$ARM64_DIGEST" --arm64-outcome "$ARM64_OUTCOME" \
|
|
--repo repo.anhonesthost.net/cloud-hosting-platform/coraza-spoa \
|
|
--repo ghcr.io/shadowdao/coraza-spoa \
|
|
--tag latest
|