Files
shopdb-flask/.github/workflows/publish-images.yml
benjamin.baker e2c34d9553 build images via remote BuildKit instead of a local docker daemon
arc-runner-set pods have no docker daemon and cannot run a privileged DinD sidecar under cluster policy, so Set up Buildx failed to connect to /var/run/docker.sock. Point Buildx at a persistent rootless buildkitd Service (driver: remote, endpoint from the BUILDKIT_ENDPOINT secret) and add its non-privileged Kubernetes manifest. Infra only; no application code changes.
2026-09-02 09:43:54 -04:00

92 lines
3.6 KiB
YAML

# Build and publish per-channel container images to GHCR.
#
# WHY this exists: pilot dev workstations sit behind an inspecting proxy
# (Zscaler) that resets npm's many small fetches mid-install, so building the
# image FROM SOURCE on a pilot box is unreliable. These runners
# (arc-runner-set) install npm cleanly - the CI `frontend` job already proves
# it - so we build the image ONCE here and pilots pull the finished image.
# A single image pull is one resumable HTTPS stream, far more robust through
# the proxy than hundreds of npm requests.
#
# Channels map to branches:
# main -> ghcr.io/<owner>/shopdb-flask:stable (badge off)
# dev-be -> ghcr.io/<owner>/shopdb-flask:edge (SHOPDB_ENV_LABEL=DEV badge)
#
# Each push to those branches rebuilds and republishes its channel tag, so
# `edge` stays genuinely bleeding edge. The image is also tagged with the short
# commit SHA for traceability and rollback.
name: publish-images
on:
push:
branches:
- main
- dev-be
# Allow a manual rebuild/publish of the current branch's channel image.
workflow_dispatch:
# One in-flight publish per branch; a newer push supersedes an older one.
concurrency:
group: publish-images-${{ github.ref }}
cancel-in-progress: true
jobs:
build-and-push:
runs-on: arc-runner-set
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v5
# Lowercase the owner: GHCR repository paths must be lowercase, but
# github.repository_owner can carry uppercase (e.g. ge-aero is fine, but
# this keeps the workflow correct for any owner casing).
- name: Resolve image name and channel tag
id: meta
run: |
owner="$(echo '${{ github.repository_owner }}' | tr '[:upper:]' '[:lower:]')"
image="ghcr.io/${owner}/shopdb-flask"
if [ "${{ github.ref_name }}" = "main" ]; then
channel="stable"
else
channel="edge"
fi
echo "image=${image}" >> "$GITHUB_OUTPUT"
echo "channel=${channel}" >> "$GITHUB_OUTPUT"
echo "sha=$(git rev-parse --short HEAD)" >> "$GITHUB_OUTPUT"
- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
# Connect to a persistent, out-of-cluster BuildKit deployment instead of
# spinning up a builder against a local Docker daemon. The arc-runner-set
# pods have no Docker daemon (no /var/run/docker.sock) and cannot run a
# privileged DinD sidecar under cluster policy, so we point Buildx at a
# remote buildkitd Service. The endpoint is provided as a repo/org secret
# (e.g. tcp://buildkit.buildkit.svc.cluster.local:1234), so it is not
# hardcoded here. See deploy/ci/buildkit-remote.yaml for the deployment.
- name: Set up Buildx (remote BuildKit)
uses: docker/setup-buildx-action@v3
with:
driver: remote
endpoint: ${{ secrets.BUILDKIT_ENDPOINT }}
- name: Build and push channel image
uses: docker/build-push-action@v6
with:
context: .
push: true
tags: |
${{ steps.meta.outputs.image }}:${{ steps.meta.outputs.channel }}
${{ steps.meta.outputs.image }}:${{ steps.meta.outputs.channel }}-${{ steps.meta.outputs.sha }}
# Reuse the channel tag as a cache source/target so subsequent builds
# only redo layers that actually changed.
cache-from: type=registry,ref=${{ steps.meta.outputs.image }}:${{ steps.meta.outputs.channel }}
cache-to: type=inline