name: Build & Push Docker Image
on:
push:
branches: [main]
workflow_dispatch:
env:
IMAGE: zebflow/zebflow
jobs:
prepare:
name: Prepare version
runs-on: ubuntu-latest
outputs:
tag: ${{ steps.version.outputs.tag }}
steps:
- uses: actions/checkout@v4
- name: Compute version
id: version
run: |
CARGO_VERSION=$(grep '^version' Cargo.toml | head -1 | sed 's/.*"\(.*\)"/\1/')
BUILD_TIME=$(date -u +"%Y%m%d%H%M")
TAG="${CARGO_VERSION}.${BUILD_TIME}"
echo "tag=${TAG}" >> $GITHUB_OUTPUT
echo "Version: ${TAG}"
build:
name: Build ${{ matrix.platform }}
runs-on: ${{ matrix.runner }}
needs: prepare
strategy:
fail-fast: false
matrix:
include:
- platform: linux/amd64
runner: ubuntu-latest
- platform: linux/arm64
runner: ubuntu-24.04-arm
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Sanitize platform name
run: echo "PLATFORM_PAIR=$(echo ${{ matrix.platform }} | tr '/' '-')" >> $GITHUB_ENV
- name: Build and push by digest
id: build
uses: docker/build-push-action@v6
with:
context: .
file: docker/Dockerfile
platforms: ${{ matrix.platform }}
build-args: BUILD_VERSION=${{ needs.prepare.outputs.tag }}
outputs: type=image,name=${{ env.IMAGE }},push-by-digest=true,name-canonical=true,push=true
cache-from: type=gha,scope=${{ env.PLATFORM_PAIR }}-v2
cache-to: type=gha,mode=max,scope=${{ env.PLATFORM_PAIR }}-v2
- name: Export digest
run: |
mkdir -p /tmp/digests
digest="${{ steps.build.outputs.digest }}"
touch "/tmp/digests/${digest#sha256:}"
- name: Upload digest artifact
uses: actions/upload-artifact@v4
with:
name: digest-${{ env.PLATFORM_PAIR }}
path: /tmp/digests/*
if-no-files-found: error
retention-days: 1
merge:
name: Merge manifest
runs-on: ubuntu-latest
needs: [prepare, build]
steps:
- name: Download digest artifacts
uses: actions/download-artifact@v4
with:
path: /tmp/digests
pattern: digest-*
merge-multiple: true
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Create and push multi-arch manifest
working-directory: /tmp/digests
run: |
docker buildx imagetools create \
-t ${{ env.IMAGE }}:${{ needs.prepare.outputs.tag }} \
-t ${{ env.IMAGE }}:latest \
$(printf '${{ env.IMAGE }}@sha256:%s ' *)
- name: Inspect final manifest
run: docker buildx imagetools inspect ${{ env.IMAGE }}:${{ needs.prepare.outputs.tag }}