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