Skip to content

Commit

Permalink
Build multi-arch docker images
Browse files Browse the repository at this point in the history
All changes listed below only touch the GH Actions config.
* Dockerize the tests
* Build JSON matrix configuration for multiple archs
* Build and test in parallel for multiple archs
* Merge the arch-specific images into a single manifest and push at the end
  • Loading branch information
dezeroku authored and anatol committed Aug 13, 2023
1 parent f533fd4 commit 3b5c82d
Show file tree
Hide file tree
Showing 2 changed files with 136 additions and 27 deletions.
161 changes: 135 additions & 26 deletions .github/workflows/push.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,55 +5,164 @@ on:
workflow_dispatch:
push:

env:
PLATFORMS: |-
linux/amd64
linux/arm64
linux/arm/v7
REGISTRY: ghcr.io
IMAGE: ${{ github.repository }}

jobs:
generate-matrix:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.generate-matrix.outputs.matrix }}
steps:
- id: generate-matrix
shell: bash
run: |
echo -n "matrix=" >> $GITHUB_OUTPUT
# Output a JSON list containing all PLATFORMS
echo "${{ env.PLATFORMS }}" | \
jq -R -c '[{ platform: . }]' | \
jq -n '{ platforms: [ [inputs[0].platform] ] | add}.platforms' -c >> $GITHUB_OUTPUT
test:
needs:
- generate-matrix
runs-on: ubuntu-latest
strategy:
# Use matrix to speed up tests
matrix:
platform: ${{ fromJSON(needs.generate-matrix.outputs.matrix) }}

steps:
- uses: actions/checkout@v3

- uses: actions/setup-go@v3
with:
go-version: '^1.17.13'
cache: true

- name: Run tests
run: go test
- name: Set up QEMU
uses: docker/setup-qemu-action@v2

- name: Build
run: go build
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2

publish_latest:
if: github.ref == 'refs/heads/master'
- name: Run tests
uses: docker/build-push-action@v4
with:
context: .
target: test
push: false
platforms: ${{ matrix.platform }}
# Enable cache to speed up builds
# Scope is to ensure that images don't overwrite each other's cache
outputs: type=cacheonly
cache-from: type=gha,scope=${{ env.REGISTRY }}-${{ github.ref_name }}-${{ matrix.platform }}-tests
cache-to: type=gha,mode=max,scope=${{ env.REGISTRY }}-${{ github.ref_name }}-${{ matrix.platform }}-tests

build:
runs-on: ubuntu-latest
strategy:
# Use matrix to speed up builds
matrix:
platform: ${{ fromJSON(needs.generate-matrix.outputs.matrix) }}

needs:
- generate-matrix
- test

steps:
- uses: actions/checkout@v3

- name: publish master to latest
uses: macbre/push-to-ghcr@master
- name: Docker meta
id: meta
uses: docker/metadata-action@v4
with:
image_name: ${{ github.repository }}
github_token: ${{ secrets.GITHUB_TOKEN }}
image_tag: latest
images: ${{ env.REGISTRY }}/${{ env.IMAGE }}

publish_release:
if: startsWith(github.ref, 'refs/tags/v')
- name: Set up QEMU
uses: docker/setup-qemu-action@v2

runs-on: ubuntu-latest
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2

- name: Login to Container Registry
uses: docker/login-action@v2
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build and push by digest
id: build
uses: docker/build-push-action@v4
with:
context: .
platforms: ${{ matrix.platform }}
labels: ${{ steps.meta.outputs.labels }}
outputs: type=image,name=${{ env.REGISTRY }}/${{ env.IMAGE }},push-by-digest=true,name-canonical=true,push=true
# Enable cache to speed up builds
# Scope is to ensure that images don't overwrite each other's cache
cache-from: type=gha,scope=${{ env.REGISTRY }}-${{ github.ref_name }}-${{ matrix.platform }}-executable
cache-to: type=gha,mode=max,scope=${{ env.REGISTRY }}-${{ github.ref_name }}-${{ matrix.platform }}-executable

- 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@v3
with:
name: digests
path: /tmp/digests/*
if-no-files-found: error
retention-days: 1


merge_and_publish:
if: (github.ref == 'refs/heads/master') || (startsWith(github.ref, 'refs/tags/'))
runs-on: ubuntu-latest
needs:
- test
- build

steps:
- uses: actions/checkout@v3
- name: Download digests
uses: actions/download-artifact@v3
with:
name: digests
path: /tmp/digests

- name: publish release to tag
uses: macbre/push-to-ghcr@master
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2

- name: Docker meta
id: meta
uses: docker/metadata-action@v4
with:
image_name: ${{ github.repository }}
github_token: ${{ secrets.GITHUB_TOKEN }}
image_tag: ${{ github.ref_name }}
images: ${{ env.REGISTRY }}/${{ env.IMAGE }}
tags: |
# tag tags with :tag
type=ref,event=tag
# tag default branch with :latest
type=raw,value=latest,enable={{is_default_branch}}
flavor: |
# Do not tag tags with :latest
latest=false
- name: Login to Container Registry
uses: docker/login-action@v2
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 $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
$(printf '${{ env.REGISTRY }}/${{ env.IMAGE }}@sha256:%s ' *)
- name: Inspect image
run: |
docker buildx imagetools inspect ${{ env.REGISTRY }}/${{ env.IMAGE }}:${{ steps.meta.outputs.version }}
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ Then start its systemd service: `# systemctl start pacoloco`.
Pacoloco can be used with docker.

You can get a prebuilt image from GitHub's [container registry](https://github.com/anatol/pacoloco/pkgs/container/pacoloco) (see also sidebar).
Currently only amd64 is supported.
Currently the images are built for `amd64` and ARM (`arm64`, `armv7`) architectures.
```sh
docker pull ghcr.io/anatol/pacoloco
```
Expand Down

0 comments on commit 3b5c82d

Please sign in to comment.