Files
haproxy-manager-base/.gitea/workflows/mirror-base-image.yaml
Josh Knapp 4e0c22e9c9
All checks were successful
Build and push coraza-spoa / Build-and-Push (push) Successful in 1m16s
HAProxy Manager Build and Push / Build-and-Push (push) Successful in 1m18s
ci: mirror golang:1.25 alongside python:3.12-slim, switch coraza-spoa FROM
Cloudflare's bot-management incident on 2026-05-12 took out docker.io blob
pulls twice in one day — first for python:3.12-slim (mirrored in 5a2ebf9),
then again for golang:1.25 when the PR 1 coraza-spoa build hit the same
R2-via-Cloudflare failure on the build stage's base image.

Restructure .gitea/workflows/mirror-base-image.yaml into a matrix that
iterates over a list of (src, dst_path, tag) entries. Adding a new base
image is now a one-line matrix entry. fail-fast: false so one image's
upstream being down doesn't block refreshing the others.

Switch coraza-spoa/Dockerfile's build stage FROM to the in-house golang
mirror. Runtime FROM (gcr.io/distroless/static-debian12:nonroot) stays
on upstream — distroless is on Google's registry, separate from Docker
Hub's Cloudflare R2 setup, and didn't fail during today's incident.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 16:40:42 -07:00

66 lines
2.5 KiB
YAML

name: Mirror base images
run-name: weekly base-image mirror
# Pulls each declared base image from upstream and re-pushes to the in-house
# registry, so any of our images that FROM these don't depend on docker.io's
# Cloudflare R2 blob storage being reachable. The 2026-05-12 Cloudflare
# incident motivated this for python:3.12-slim and again for golang:1.25
# when the coraza-spoa build hit the same blob-fetch failure.
#
# Adding a new mirror = add one entry to the matrix below. The destination
# tag is always cloud-hosting-platform/<image>:<tag>, matching upstream.
on:
schedule:
# Mondays 06:00 UTC — outside customer peak hours and well before the
# typical Tuesday/Thursday push cycles. workflow_dispatch lets us trigger
# manually from the Gitea UI when upstream publishes patches.
- cron: '0 6 * * 1'
workflow_dispatch:
jobs:
Mirror-Base:
runs-on: ubuntu-latest
strategy:
# fail-fast=false so one image's upstream being down doesn't block the
# others from refreshing.
fail-fast: false
matrix:
image:
- { src: 'docker.io/library/python:3.12-slim', dst_path: 'cloud-hosting-platform/python', tag: '3.12-slim' }
- { src: 'docker.io/library/golang:1.25', dst_path: 'cloud-hosting-platform/golang', tag: '1.25' }
steps:
- name: Login to in-house registry
uses: docker/login-action@v3
with:
registry: repo.anhonesthost.net
username: ${{ secrets.CI_USER }}
password: ${{ secrets.CI_TOKEN }}
- name: Pull, retag, push ${{ matrix.image.src }}
run: |
set -euo pipefail
SRC="${{ matrix.image.src }}"
DST="repo.anhonesthost.net/${{ matrix.image.dst_path }}:${{ matrix.image.tag }}"
echo "::group::Pulling ${SRC}"
docker pull "${SRC}"
echo "::endgroup::"
# Capture the upstream digest so the workflow log shows what we
# actually pushed. Helps diagnose "did the mirror really update"
# questions later.
SRC_DIGEST=$(docker image inspect "${SRC}" -f '{{index .RepoDigests 0}}')
echo "upstream digest: ${SRC_DIGEST}"
docker tag "${SRC}" "${DST}"
echo "::group::Pushing ${DST}"
docker push "${DST}"
echo "::endgroup::"
# Sanity: the in-house tag should now resolve to the same content.
DST_DIGEST=$(docker image inspect "${DST}" -f '{{index .RepoDigests 0}}')
echo "mirror digest: ${DST_DIGEST}"