Skip to content

Commit

Permalink
feat(actions): run build parallel on multiple runners and build arm n…
Browse files Browse the repository at this point in the history
…atively

also adds reusable workflow for this building way
  • Loading branch information
JuniorJPDJ authored Feb 16, 2025
1 parent 1f96211 commit 4aef4f6
Show file tree
Hide file tree
Showing 2 changed files with 256 additions and 70 deletions.
242 changes: 242 additions & 0 deletions .github/workflows/docker-parallel-multiarch-build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,242 @@
name: Build and push docker container (parallelized multi-arch build with native arm builders)

on:
workflow_call:
inputs:
context:
default: "."
required: false
type: string
file:
required: false
type: string

title:
required: true
type: string
description:
required: false
type: string

app-version:
default: '0.1.0'
required: false
type: string
revision:
default: 1
required: false
type: number

platforms:
default: 'linux/amd64,linux/arm64'
required: false
type: string
buildkit-mount-caches:
description: "JSON object: `{id1: target1, id2: target2}`."
required: false
type: string
buildkit-mount-cache-ids-append-platform:
description: "If true, the workflow will append `-{{ platform }}` to the end of cache mount id (eg. `-linux/amd64`)."
default: false
type: boolean

registry:
default: ghcr.io
required: false
type: string
image-name:
required: true
type: string
secrets:
registry-username:
required: true
registry-password:
required: true

jobs:
vars:
name: Preprocess variables
runs-on: ubuntu-24.04
steps:
- name: Preprocess variables
id: vars
run: |
platforms="${{ inputs.platforms }}"
{
echo "version=${{ inputs.app-version }}-r${{ inputs.revision }}"
echo "platforms<<9743a66f914cc249efca164485a19c5c"
echo "[\"${platforms//,/\",\"}\"]"
echo "9743a66f914cc249efca164485a19c5c"
} >> "$GITHUB_OUTPUT"
outputs:
version: ${{ steps.vars.outputs.version }}
platforms: ${{ steps.vars.outputs.platforms }}

build:
name: Build container for ${{ matrix.platform }}
runs-on: ${{ startsWith(matrix.platform, 'linux/arm') && 'ubuntu-24.04-arm' || 'ubuntu-24.04' }}
needs: vars
permissions:
contents: read
packages: write
# This is used to complete the identity challenge
# with sigstore/fulcio when running outside of PRs.
id-token: write
strategy:
fail-fast: false
matrix:
platform: ${{ fromJSON(needs.vars.outputs.platforms) }}
steps:
- name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

# Workaround: https://github.com/docker/build-push-action/issues/461
- name: Setup Docker buildx
uses: docker/setup-buildx-action@f7ce87c1d6bead3e36075b2ce75da1f6cc28aaca # v3.9.0

- name: Log into registry ${{ inputs.registry }}
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0
with:
registry: ${{ inputs.registry }}
username: ${{ secrets.registry-username }}
password: ${{ secrets.registry-password }}

- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@369eb591f429131d6889c46b94e711f089e6ca96 # v5.6.1
with:
images: ${{ inputs.registry }}/${{ inputs.image-name }}
labels: |
org.opencontainers.image.title=${{ inputs.title }}
org.opencontainers.image.description=${{ inputs.description }}
- name: Prepare variables
id: vars
run: |
platform='${{ matrix.platform }}'
image='${{ steps.meta.outputs.tags }}'
[ '${{ inputs.buildkit-mount-cache-ids-append-platform }}' = 'true' ] && id_suffix='-${{ matrix.platform }}'
{
echo "platform-pair=${platform//\//-}"
echo "platform-pair-un=${platform//\//_}"
echo "image=${image%%:*}"
echo "cache-map<<9743a66f914cc249efca164485a19c5c"
jq --arg 'id_suffix' "$id_suffix" 'to_entries | map({(.key): {target: .value, id: "\(.key)\($id_suffix)"}}) | add' << 9743a66f914cc249efca164485a19c5c
${{ inputs.buildkit-mount-caches }}
9743a66f914cc249efca164485a19c5c
echo "9743a66f914cc249efca164485a19c5c"
echo "cache-paths<<9743a66f914cc249efca164485a19c5c"
jq -r 'to_entries | .[].key' << 9743a66f914cc249efca164485a19c5c
${{ inputs.buildkit-mount-caches }}
9743a66f914cc249efca164485a19c5c
echo "9743a66f914cc249efca164485a19c5c"
} >> $GITHUB_OUTPUT
cat $GITHUB_OUTPUT
- name: Setup buildkit mount cache
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
if: steps.vars.outputs.cache-paths
with:
path: |
${{ steps.vars.outputs.cache-paths }}
key: buildkit-mount-${{ inputs.title }}-${{ steps.vars.outputs.platform-pair }}-${{ github.sha }}
restore-keys: |
buildkit-mount-${{ inputs.title }}-${{ steps.vars.outputs.platform-pair }}-
- name: Inject buildkit mount cache into docker
uses: reproducible-containers/buildkit-cache-dance@5b6db76d1da5c8b307d5d2e0706d266521b710de # v3.1.2
if: steps.vars.outputs.cache-paths
with:
cache-map: |
${{ steps.vars.outputs.cache-map }}
- name: Build and push Docker image
id: build-and-push
uses: docker/build-push-action@ca877d9245402d1537745e0e356eab47c3520991 # v6.13.0
with:
context: ${{ inputs.context }}
file: ${{ inputs.file }}
push: true
platforms: ${{ matrix.platform }}
outputs: type=image,"name=${{ steps.vars.outputs.image }}",push-by-digest=true,name-canonical=true,push=true
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha,scope=buildkit-layer-${{ inputs.title }}-${{ steps.vars.outputs.platform-pair }}
cache-to: type=gha,mode=max,scope=buildkit-layer-${{ inputs.title }}-${{ steps.vars.outputs.platform-pair }}

# Workaround for https://github.com/actions/runner/pull/2477
- name: Export digest
run: |
mkdir -p ${{ runner.temp }}/digests
digest="${{ steps.build-and-push.outputs.digest }}"
touch "${{ runner.temp }}/digests/${digest#sha256:}"
- name: Upload digest as an artifact
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: digests-${{ inputs.title }}-${{ steps.vars.outputs.platform-pair }}
path: ${{ runner.temp }}/digests/*
if-no-files-found: error
retention-days: 1

outputs:
image: ${{ steps.vars.outputs.image }}
# https://github.com/actions/runner/pull/2477 :<
# ${{ steps.vars.outputs.platform-pair-un }}-digest: ${{ steps.build-and-push.outputs.digest }}

merge:
name: Merge images to multi-arch image
runs-on: ubuntu-24.04
permissions:
contents: read
packages: write
# This is used to complete the identity challenge
# with sigstore/fulcio when running outside of PRs.
id-token: write
needs:
- build
steps:
- name: Download digests
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
with:
path: ${{ runner.temp }}/digests
pattern: digests-${{ inputs.title }}-*
merge-multiple: true

# Workaround: https://github.com/docker/build-push-action/issues/461
- name: Setup Docker buildx
uses: docker/setup-buildx-action@f7ce87c1d6bead3e36075b2ce75da1f6cc28aaca # v3.9.0

- name: Log into registry ${{ inputs.registry }}
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0
with:
registry: ${{ inputs.registry }}
username: ${{ secrets.registry-username }}
password: ${{ secrets.registry-password }}

- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@369eb591f429131d6889c46b94e711f089e6ca96 # v5.6.1
with:
images: ${{ inputs.registry }}/${{ inputs.image-name }}
labels: |
org.opencontainers.image.title=${{ inputs.title }}
org.opencontainers.image.description=${{ inputs.description }}
tags: |
type=ref,event=branch,priority=1990
type=ref,event=pr,priority=2999
type=raw,value=latest,enable={{is_default_branch}}
type=raw,enable={{is_default_branch}},value=${{ needs.vars.outputs.version }},priority=1999
type=raw,enable={{is_default_branch}},value=${{ inputs.app-version }},priority=1998
type=semver,enable={{is_default_branch}},value=${{ inputs.app-version }},pattern={{major}}.{{minor}},priority=1997
type=semver,enable={{is_default_branch}},value=${{ inputs.app-version }},pattern={{major}},priority=1996
- 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 '${{ needs.build.outputs.image }}@sha256:%s ' *)
84 changes: 14 additions & 70 deletions .github/workflows/docker-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,10 @@ on:
types: [opened, reopened, synchronize]
workflow_dispatch:

env:
REGISTRY: ghcr.io

jobs:
list_containers:
name: List containers to build
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
outputs:
matrix: ${{ steps.set-matrix.outputs.MATRIX }}
steps:
Expand Down Expand Up @@ -46,7 +43,6 @@ jobs:
build:
name: "Build container: ${{ matrix.container }}"
runs-on: ubuntu-latest
needs: list_containers
permissions:
contents: read
Expand All @@ -59,68 +55,16 @@ jobs:
fail-fast: false
matrix:
include: ${{ fromJSON(needs.list_containers.outputs.matrix) }}

steps:
- name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

- name: Generate properties
id: props
run: |
PLATFORMS_DEFAULT="linux/amd64,linux/arm64"
APP_VERSION_DEFAULT="0.1.0"
REVISION_DEFAULT="1"
PLATFORMS="${{ matrix.platforms }}"
APP_VERSION="${{ matrix.app_version }}"
REVISION="${{ matrix.revision }}"
platforms="${PLATFORMS:-"${PLATFORMS_DEFAULT}"}"
app_version="${APP_VERSION:-"${APP_VERSION_DEFAULT}"}"
revision="${REVISION:-"${REVISION_DEFAULT}"}"
{
echo "platforms=$platforms"
echo "app_version=$app_version"
echo "revision=$revision"
echo "version=${app_version}-r${revision}"
} >> "$GITHUB_OUTPUT"
# Workaround: https://github.com/docker/build-push-action/issues/461
- name: Setup Docker buildx
uses: docker/setup-buildx-action@f7ce87c1d6bead3e36075b2ce75da1f6cc28aaca # v3.9.0

- name: Log into registry ${{ env.REGISTRY }}
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@369eb591f429131d6889c46b94e711f089e6ca96 # v5.6.1
with:
images: ${{ env.REGISTRY }}/${{ github.repository }}/${{ matrix.container }}
labels: |
org.opencontainers.image.title=${{ matrix.container }}
org.opencontainers.image.description=${{ matrix.description }}
tags: |
type=ref,event=branch,priority=1990
type=ref,event=pr,priority=2999
type=raw,value=latest,enable={{is_default_branch}}
type=raw,enable={{is_default_branch}},value=${{ steps.props.outputs.version }},priority=1999
type=raw,enable={{is_default_branch}},value=${{ steps.props.outputs.app_version }},priority=1998
type=semver,enable={{is_default_branch}},value=${{ steps.props.outputs.app_version }},pattern={{major}}.{{minor}},priority=1997
type=semver,enable={{is_default_branch}},value=${{ steps.props.outputs.app_version }},pattern={{major}},priority=1996
- name: Build and push Docker image
id: build-and-push
uses: docker/build-push-action@ca877d9245402d1537745e0e356eab47c3520991 # v6.13.0
with:
context: containers/${{ matrix.container }}
push: true
platforms: ${{ steps.props.outputs.platforms }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
uses: ./.github/workflows/docker-parallel-multiarch-build.yml
with:
context: containers/${{ matrix.container }}
title: ${{ matrix.container }}
description: ${{ matrix.description }}
app-version: ${{ matrix.app_version }}
revision: ${{ fromJSON(matrix.revision) }}
platforms: ${{ matrix.platforms }}
registry: ghcr.io
image-name: ${{ github.repository }}/${{ matrix.container }}
secrets:
registry-username: ${{ github.actor }}
registry-password: ${{ secrets.GITHUB_TOKEN }}

0 comments on commit 4aef4f6

Please sign in to comment.