Files
buzz/.github/workflows/loadgen-image.yml

223 lines
7.5 KiB
YAML

name: Loadgen image
# Builds and publishes the relay load generator image as
# ghcr.io/block/buzz-loadgen (see Dockerfile.loadgen and perf/LOADGEN.md).
#
# Strategy mirrors sprig-image.yml: each architecture builds on its native
# runner, pushes to GHCR by digest, then a merge job stitches the per-arch
# digests into one multi-arch manifest and attests provenance.
#
# Triggers:
# - push to main (paths-filtered) → :main + :sha-<7>
# - pull_request (paths-filtered) → build only, no image push (same-repo
# PRs still write the registry build cache, as in sprig-image.yml)
# - workflow_dispatch → manual publish at the current ref
#
# NOTE: the first push creates the GHCR package PRIVATE by default. An org
# admin must flip ghcr.io/block/buzz-loadgen to public once (Package settings →
# Change visibility). Subsequent pushes keep the visibility.
on:
push:
branches: [main]
paths:
- "Dockerfile.loadgen"
- ".github/workflows/loadgen-image.yml"
- ".cargo/config.toml"
- "Cargo.toml"
- "Cargo.lock"
- "rust-toolchain.toml"
- "crates/buzz-test-client/**"
- "crates/buzz-ws-client/**"
- "crates/buzz-core/**"
pull_request:
paths:
- "Dockerfile.loadgen"
- ".github/workflows/loadgen-image.yml"
workflow_dispatch: {}
concurrency:
group: loadgen-image-${{ github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
permissions: {}
env:
IMAGE_NAME: ghcr.io/block/buzz-loadgen
jobs:
build:
name: Build (${{ matrix.platform }})
runs-on: ${{ matrix.runner }}
timeout-minutes: 60
permissions:
contents: read
packages: write
id-token: write
attestations: write
strategy:
fail-fast: false
matrix:
include:
- platform: linux/amd64
runner: ubuntu-24.04
arch: amd64
- platform: linux/arm64
runner: ubuntu-24.04-arm
arch: arm64
steps:
- name: Checkout
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
persist-credentials: false
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
with:
# Same OOM cap as docker.yml and sprig-image.yml.
buildkitd-config-inline: |
[worker.oci]
max-parallelism = 2
- name: Log in to GHCR
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9 # v6.1.0
with:
images: ${{ env.IMAGE_NAME }}
flavor: |
latest=false
tags: |
type=ref,event=branch
type=sha,prefix=sha-,format=short
labels: |
org.opencontainers.image.title=Buzz Loadgen
org.opencontainers.image.description=Scenario-driven Buzz relay load generator
org.opencontainers.image.licenses=Apache-2.0
- name: Build and push by digest
id: build
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
with:
context: .
file: ./Dockerfile.loadgen
platforms: ${{ matrix.platform }}
labels: ${{ steps.meta.outputs.labels }}
outputs: type=image,name=${{ env.IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=${{ github.event_name != 'pull_request' }}
cache-from: |
type=registry,ref=${{ env.IMAGE_NAME }}-buildcache:${{ matrix.arch }}
cache-to: |
${{ (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) && format('type=registry,ref={0}-buildcache:{1},mode=max,compression=zstd', env.IMAGE_NAME, matrix.arch) || '' }}
- name: Export digest
if: github.event_name != 'pull_request'
env:
DIGEST: ${{ steps.build.outputs.digest }}
run: |
mkdir -p /tmp/digests
touch "/tmp/digests/${DIGEST#sha256:}"
- name: Upload digest
if: github.event_name != 'pull_request'
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: loadgen-digest-${{ matrix.arch }}
path: /tmp/digests/*
if-no-files-found: error
retention-days: 1
merge:
name: Merge multi-arch manifest
if: github.event_name != 'pull_request'
runs-on: ubuntu-24.04
needs: build
timeout-minutes: 15
permissions:
contents: read
packages: write
id-token: write
attestations: write
steps:
- name: Download per-arch digests
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
path: /tmp/digests
pattern: loadgen-digest-*
merge-multiple: true
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
- name: Log in to GHCR
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9 # v6.1.0
with:
images: ${{ env.IMAGE_NAME }}
# Must mirror the build job's tag matrix exactly.
flavor: |
latest=false
tags: |
type=ref,event=branch
type=sha,prefix=sha-,format=short
- name: Create and push manifest list
id: manifest
working-directory: /tmp/digests
env:
IMAGE_NAME: ${{ env.IMAGE_NAME }}
META_TAGS: ${{ steps.meta.outputs.tags }}
run: |
set -euo pipefail
tags=()
while IFS= read -r tag; do
[ -n "$tag" ] && tags+=("-t" "$tag")
done <<< "$META_TAGS"
digests=()
for digest in *; do
digests+=("${IMAGE_NAME}@sha256:${digest}")
done
docker buildx imagetools create "${tags[@]}" "${digests[@]}"
first_tag=$(echo "$META_TAGS" | head -n1)
merged_digest=$(docker buildx imagetools inspect "$first_tag" \
--format '{{json .Manifest}}' | jq -r '.digest')
echo "digest=${merged_digest}" >> "$GITHUB_OUTPUT"
- name: Attest provenance for the merged image
# Verify with: gh attestation verify oci://ghcr.io/block/buzz-loadgen:<tag> --owner block
uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4.1.1
with:
subject-name: ${{ env.IMAGE_NAME }}
subject-digest: ${{ steps.manifest.outputs.digest }}
push-to-registry: true
- name: Summary
env:
IMAGE_NAME: ${{ env.IMAGE_NAME }}
DIGEST: ${{ steps.manifest.outputs.digest }}
run: |
{
echo "### Loadgen image published"
echo '```'
echo "${IMAGE_NAME}@${DIGEST}"
echo '```'
} >> "$GITHUB_STEP_SUMMARY"