Add support for building and publishing multi-architecture Docker images (amd64 and arm64) using a matrix strategy. Introduce a new 'prepare' job for metadata computation and a 'merge' job for creating manifest lists. Enable manual workflow dispatch with optional latest tagging. Improve caching and provenance handling for better efficiency and reliability.
151 lines
4.6 KiB
YAML
151 lines
4.6 KiB
YAML
name: Create and publish Docker images
|
|
|
|
on:
|
|
push:
|
|
tags:
|
|
- 'v*.*.*'
|
|
workflow_dispatch:
|
|
inputs:
|
|
use_latest_tag:
|
|
description: 'Tag as latest instead of branch name'
|
|
required: false
|
|
type: boolean
|
|
default: false
|
|
|
|
env:
|
|
REGISTRY: ghcr.io
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
jobs:
|
|
prepare:
|
|
runs-on: ubuntu-24.04
|
|
outputs:
|
|
image_name: ${{ steps.image-name.outputs.image_name }}
|
|
tags: ${{ steps.meta.outputs.tags }}
|
|
labels: ${{ steps.meta.outputs.labels }}
|
|
steps:
|
|
- name: Compute lowercase image name
|
|
id: image-name
|
|
run: echo "image_name=${GITHUB_REPOSITORY,,}" >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Extract metadata (tags, labels) for Docker
|
|
id: meta
|
|
uses: docker/metadata-action@v5
|
|
with:
|
|
images: ${{ env.REGISTRY }}/${{ steps.image-name.outputs.image_name }}
|
|
tags: |
|
|
type=raw,value=latest,enable=${{ (github.event_name == 'push' && !contains(github.ref, '-pre')) || (github.event_name == 'workflow_dispatch' && inputs.use_latest_tag == true) }},priority=1000
|
|
type=semver,pattern={{version}}
|
|
type=ref,event=tag
|
|
type=ref,event=branch,enable=${{ github.event_name == 'workflow_dispatch' && inputs.use_latest_tag != true }}
|
|
|
|
build:
|
|
needs: prepare
|
|
runs-on: ${{ matrix.runner }}
|
|
permissions:
|
|
actions: write
|
|
contents: read
|
|
packages: write
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
include:
|
|
- arch: amd64
|
|
platform: linux/amd64
|
|
runner: ubuntu-24.04
|
|
- arch: arm64
|
|
platform: linux/arm64
|
|
runner: ubuntu-24.04-arm
|
|
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@v4
|
|
with:
|
|
ref: ${{ github.sha }}
|
|
fetch-depth: 0
|
|
|
|
- name: Set up Docker Buildx
|
|
uses: docker/setup-buildx-action@v3
|
|
|
|
- name: Login to GitHub Container Registry
|
|
uses: docker/login-action@v3
|
|
with:
|
|
registry: ${{ env.REGISTRY }}
|
|
username: ${{ github.actor }}
|
|
password: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- name: Build and push Docker image (${{ matrix.arch }})
|
|
id: build
|
|
uses: docker/build-push-action@v5
|
|
with:
|
|
context: .
|
|
platforms: ${{ matrix.platform }}
|
|
labels: ${{ needs.prepare.outputs.labels }}
|
|
cache-from: type=gha,scope=${{ matrix.arch }}
|
|
cache-to: type=gha,mode=max,scope=${{ matrix.arch }}
|
|
provenance: false
|
|
outputs: type=image,name=${{ env.REGISTRY }}/${{ needs.prepare.outputs.image_name }},push-by-digest=true,name-canonical=true,push=true
|
|
|
|
- name: Export digest
|
|
run: |
|
|
mkdir -p /tmp/digests
|
|
digest="${{ steps.build.outputs.digest }}"
|
|
touch "/tmp/digests/${digest#sha256:}"
|
|
|
|
- name: Upload digest
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: digests-${{ matrix.arch }}
|
|
path: /tmp/digests
|
|
if-no-files-found: error
|
|
retention-days: 1
|
|
|
|
merge:
|
|
needs: [prepare, build]
|
|
runs-on: ubuntu-24.04
|
|
permissions:
|
|
actions: read
|
|
contents: read
|
|
packages: write
|
|
|
|
steps:
|
|
- name: Download digests
|
|
uses: actions/download-artifact@v4
|
|
with:
|
|
path: /tmp/digests
|
|
pattern: digests-*
|
|
merge-multiple: true
|
|
|
|
- name: Set up Docker Buildx
|
|
uses: docker/setup-buildx-action@v3
|
|
|
|
- name: Login to GitHub Container Registry
|
|
uses: docker/login-action@v3
|
|
with:
|
|
registry: ${{ env.REGISTRY }}
|
|
username: ${{ github.actor }}
|
|
password: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- name: Create manifest list and push
|
|
working-directory: /tmp/digests
|
|
run: |
|
|
docker buildx imagetools create \
|
|
$(echo "$TAGS" | xargs -I {} echo -t {}) \
|
|
$(printf '${{ env.REGISTRY }}/${{ needs.prepare.outputs.image_name }}@sha256:%s ' *)
|
|
env:
|
|
TAGS: ${{ needs.prepare.outputs.tags }}
|
|
|
|
- name: Output build information
|
|
run: |
|
|
echo "✅ Docker images built and pushed successfully!"
|
|
echo "🐋 Images:"
|
|
echo '${{ needs.prepare.outputs.tags }}' | sed 's/^/ - /'
|
|
echo "📝 Event: ${{ github.event_name }}"
|
|
if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
|
|
echo "📝 Triggered by manual workflow dispatch on branch: ${{ github.ref_name }}"
|
|
echo "📝 use_latest_tag: ${{ inputs.use_latest_tag }}"
|
|
else
|
|
echo "📝 Triggered by tag: ${{ github.ref_name }}"
|
|
fi
|