Files
pl_mail/.github/workflows/docker.yml
T
Paul LütznerandClaude Opus 5 dc0647f23f Publish latest from release tags, add a changelog, unstale the roadmap
latest followed the default branch, so every push to main went straight
to the tag the README tells people to pull — including work in progress,
and migrations that run automatically on boot. It now moves only on a v*
tag; main still publishes under its own name for anyone wanting the tip.

The roadmap listed three finished things as open, including the label
refactor and the nested label UI, both of which shipped. A roadmap that
under-reports is worse than none: it is the document a contributor reads
to decide what to pick up. Corrected, with the genuinely open items
described accurately and a note asking that it be kept honest.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-31 12:28:42 +02:00

151 lines
5.9 KiB
YAML

name: Build and push Docker image
on:
push:
branches: [main]
# Releases. `latest` moves only when one of these is pushed — see the
# tag rules in the merge job.
tags: ['v*']
pull_request:
branches: [main]
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
# One job per architecture, each on a runner of that architecture. The prod
# stage runs composer install, dump-autoload, tailwind:build --minify and
# asset-map:compile — all CPU-bound PHP, which is why this is a matrix of
# native runners rather than a single job cross-building under QEMU.
#
# Neither job pushes a tag. Both push an untagged digest, and `merge` below
# assembles them into the one manifest list the tags point at.
build:
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: false
matrix:
include:
- platform: linux/amd64
arch: amd64
runner: ubuntu-latest
- platform: linux/arm64
arch: arm64
runner: ubuntu-24.04-arm
permissions:
contents: read
packages: write
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
# Labels only. Tags belong to the manifest list, which does not
# exist until the merge job runs.
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
- name: Build and push by digest
id: build
uses: docker/build-push-action@v6
with:
context: .
target: frankenphp_prod
platforms: ${{ matrix.platform }}
labels: ${{ steps.meta.outputs.labels }}
provenance: false
outputs: type=image,name=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=${{ github.event_name != 'pull_request' }}
# Scoped per architecture: a shared scope would have the two
# jobs evicting each other's layers on every run.
cache-from: type=gha,scope=frankenphp_prod-${{ matrix.arch }}
cache-to: type=gha,mode=max,scope=frankenphp_prod-${{ matrix.arch }}
- name: Export digest
if: github.event_name != 'pull_request'
run: |
digest="${{ steps.build.outputs.digest }}"
mkdir -p "${{ runner.temp }}/digests"
touch "${{ runner.temp }}/digests/${digest#sha256:}"
shell: bash
- name: Upload digest
if: github.event_name != 'pull_request'
uses: actions/upload-artifact@v4
with:
name: digests-${{ matrix.arch }}
path: ${{ runner.temp }}/digests/*
if-no-files-found: error
retention-days: 1
# Collects the per-architecture digests into a single manifest list and
# applies the tags to it. Pull requests never push, so there is nothing to
# merge for them.
merge:
runs-on: ubuntu-latest
needs: build
if: github.event_name != 'pull_request'
permissions:
contents: read
packages: write
steps:
- name: Download digests
uses: actions/download-artifact@v4
with:
path: ${{ runner.temp }}/digests
pattern: digests-*
merge-multiple: true
- name: Set up Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
# `latest` used to follow the default branch, so every push
# to main went straight to the tag the README tells people to
# pull — including work in progress, and migrations that run
# automatically on boot. It now moves only on a release tag.
#
# `main` still publishes, under its own name, for anyone who
# wants the tip.
tags: |
type=ref,event=branch
type=sha,prefix=sha-
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=raw,value=latest,enable=${{ startsWith(github.ref, 'refs/tags/v') }}
- name: Create manifest list and push
working-directory: ${{ runner.temp }}/digests
run: |
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
$(printf '${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@sha256:%s ' *)
- name: Inspect image
run: |
docker buildx imagetools inspect ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.version }}