Skip to content

Commit c09f3fb

Browse files
authored
ci: Build multiple docker using multiple runners (#1)
* ci: Build multiple docker using multiple runners * ci: Compute versions once
1 parent 844d7c4 commit c09f3fb

1 file changed

Lines changed: 103 additions & 34 deletions

File tree

.github/workflows/publish.yml

Lines changed: 103 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -4,47 +4,64 @@ on:
44
push:
55
branches:
66
- master
7+
- multi-runner-docker
78
tags:
89
- v**
910
workflow_dispatch:
1011

11-
jobs:
12-
publish:
13-
name: Publish Docker Image to ghcr.io
14-
runs-on: ubuntu-latest
15-
permissions:
16-
packages: write
12+
env:
13+
REGISTRY: ghcr.io
14+
IMAGE: ${{ github.repository }}
1715

16+
jobs:
17+
gen-versions:
18+
name: Generate tags
19+
runs-on: ubuntu-24.04
20+
outputs:
21+
DOCKER_IMAGE_TAG_JSON: ${{ steps.variables.outputs.DOCKER_IMAGE_TAG_JSON }}
22+
DOCKER_IMAGE_TAG: ${{ steps.variables.outputs.DOCKER_IMAGE_TAG }}
1823
steps:
19-
- name: Check out the repo
20-
uses: actions/checkout@v4
21-
2224
- name: Setup variables
25+
id: variables
2326
run: |
2427
# docker/build-push-action supports comma separated tags
25-
DOCKER_IMAGE_TAG_BASE="ghcr.io/${{ github.repository }}"
26-
DOCKER_IMAGE_TAGS="$DOCKER_IMAGE_TAG_BASE:dev"
28+
DOCKER_IMAGE_TAG_BASE="$REGISTRY/$IMAGE"
29+
DOCKER_IMAGE_TAG_JSON="$(
30+
( # Every line echoed inside of these parenthesis will result in a version
31+
echo dev
32+
GH_REF="${{ github.ref }}"
33+
# if this is a versioned release, github.ref will start with 'refs/tags/v'
34+
# cut off 'refs/tags/v'
35+
if [[ $GH_REF == "refs/tags/v"* ]]; then
36+
VERSION=$(echo $GH_REF | cut -c 12-)
37+
echo latest
38+
echo $VERSION
39+
fi
40+
) | sed -e 's|.*|'"$DOCKER_IMAGE_TAG_BASE"':\0|' | jq -R -s -c 'split("\n") | map(select (. != "" ))')"
2741
28-
# if this is a versioned release, github.ref will start with 'refs/tags/v'
29-
GH_REF="${{ github.ref }}"
30-
# cut off 'refs/tags/v'
31-
if [[ $GH_REF == "refs/tags/v"* ]]; then
32-
VERSION=$(echo $GH_REF | cut -c 12-)
33-
DOCKER_IMAGE_TAGS="$DOCKER_IMAGE_TAGS,$DOCKER_IMAGE_TAG_BASE:latest,$DOCKER_IMAGE_TAG_BASE:$VERSION"
34-
fi
42+
echo "DOCKER_IMAGE_TAG_JSON=$DOCKER_IMAGE_TAG_JSON" >> "$GITHUB_OUTPUT"
43+
echo "DOCKER_IMAGE_TAG=$(echo "$DOCKER_IMAGE_TAG_JSON" | jq -r 'join(",")')" >> "$GITHUB_OUTPUT"
3544
36-
echo "DOCKER_IMAGE_TAGS=\"$DOCKER_IMAGE_TAGS\"" >> $GITHUB_ENV
37-
# this is dumb
38-
echo "VERSION=$VERSION" >> $GITHUB_ENV
45+
publish-base:
46+
name: Publish ${{ matrix.arch }} image
47+
strategy:
48+
matrix:
49+
include:
50+
- arch: arm64
51+
os: ubuntu-24.04-arm
52+
- arch: amd64
53+
os: ubuntu-24.04
3954

40-
- name: Check if version already exists in registry
41-
run: |
42-
# this is still dumb
43-
VERSION=${{ env.VERSION }}
44-
if docker manifest inspect ghcr.io/${{ github.repository }}:$VERSION > /dev/null 2>&1; then
45-
echo "Image with version $VERSION already exists in registry"
46-
exit 1
47-
fi
55+
runs-on: ${{ matrix.os }}
56+
needs:
57+
- gen-versions
58+
env:
59+
ARCH: ${{matrix.arch}}
60+
permissions:
61+
packages: write
62+
steps:
63+
- name: Check out the repo
64+
uses: actions/checkout@v4
4865

4966
- name: Log in to ghcr.io
5067
uses: docker/login-action@v3
@@ -53,16 +70,68 @@ jobs:
5370
username: ${{ github.actor }}
5471
password: ${{ secrets.GITHUB_TOKEN }}
5572

56-
- name: Set up Docker Buildx
73+
- name: Enhance tags
74+
id: variables
75+
run: |
76+
echo "DOCKER_IMAGE_TAG=$(echo "$TAG" | jq -r 'map(. + "-${{ matrix.arch }}") | join(",")')" >>"$GITHUB_OUTPUT"
77+
env:
78+
TAG: ${{ needs.gen-versions.outputs.DOCKER_IMAGE_TAG_JSON }}
79+
- name: Set up Docker Buildx # Even if we don't directly invoke buildx it should set up github action caches, which is nice
5780
uses: docker/setup-buildx-action@v3
58-
5981
- name: Build and push Docker Image
6082
uses: docker/build-push-action@v6
83+
id: upload-docker-image
6184
with:
6285
context: .
63-
file: ./Dockerfile
6486
push: true
65-
tags: ${{ env.DOCKER_IMAGE_TAGS }}
66-
platforms: linux/amd64
87+
tags: ${{ steps.variables.outputs.DOCKER_IMAGE_TAG }}
6788
cache-from: type=gha
6889
cache-to: type=gha,mode=max
90+
- name: Write digest
91+
run: |
92+
digest="${{ steps.upload-docker-image.outputs.digest }}"
93+
mkdir -p digests
94+
touch "digests/${digest#sha256:}"
95+
96+
- name: Upload docker image digest
97+
uses: actions/upload-artifact@v4
98+
with:
99+
if-no-files-found: error
100+
name: digests-${{ matrix.arch }}
101+
path: digests/*
102+
103+
publish-multiarch:
104+
name: Publish multi-arch image
105+
needs:
106+
- publish-base
107+
- gen-versions
108+
runs-on: ubuntu-24.04
109+
permissions:
110+
packages: write
111+
steps:
112+
- name: Download digests
113+
uses: actions/download-artifact@v4
114+
with:
115+
path: digests
116+
pattern: digests-*
117+
merge-multiple: true
118+
119+
- name: Log in to ghcr.io
120+
uses: docker/login-action@v3
121+
with:
122+
registry: ghcr.io
123+
username: ${{ github.actor }}
124+
password: ${{ secrets.GITHUB_TOKEN }}
125+
126+
127+
- name: Set up Docker Buildx
128+
uses: docker/setup-buildx-action@v3
129+
130+
- name: Create manifest list
131+
run: |
132+
cd digests
133+
docker buildx imagetools create \
134+
`# A -t {tag} for each tag in DOCKER_IMAGE_TAGS` \
135+
$(echo '${{ needs.gen-versions.outputs.DOCKER_IMAGE_TAG }}'| tr ',' '\n' | sed -e 's|.*|-t \0|') \
136+
`# Then a reference for each of the arches. This uses the fact that printf repeats its format string if it has too many arguments.` \
137+
$(printf '${{env.REGISTRY}}/${{ env.IMAGE }}@sha256:%s ' *)

0 commit comments

Comments
 (0)