Skip to content

Commit 620d127

Browse files
committed
[CI] Merge docker images across platforms
With the current setup, images for different platforms are pushed with the same tag, overriding each other. With this change, instead, images built for different architectures are merged together. [skip ci]
1 parent 5d9474a commit 620d127

File tree

1 file changed

+100
-19
lines changed

1 file changed

+100
-19
lines changed

.github/workflows/Container.yml

Lines changed: 100 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
# Based on
2+
# * <https://github.com/NumericalEarth/breeze-docker-images/blob/f06a3da11b2c7edaaf0a8e32c133270eb4103b1c/.github/workflows/DockerPublish.yml>
3+
# * <https://docs.github.com/en/actions/publishing-packages/publishing-docker-images>
4+
# * <https://docs.docker.com/build/ci/github-actions/multi-platform/#distribute-build-across-multiple-runners>.
5+
16
name: Publish Docker container
27

38
on:
@@ -18,12 +23,20 @@ on:
1823
branches:
1924
- master
2025

26+
env:
27+
REGISTRY: ghcr.io
28+
IMAGE_NAME: ${{ github.repository }}
29+
2130
jobs:
22-
push_to_registry:
23-
name: Container for ${{ matrix.platform }} - Julia ${{ matrix.julia }} - CUDA ${{ matrix.cuda }}
31+
build:
32+
name: Build Container for ${{ matrix.platform }} - Julia ${{ matrix.julia }} - CUDA ${{ matrix.cuda }}
2433
permissions:
2534
contents: read
2635
packages: write
36+
attestations: write
37+
# This is used to complete the identity challenge
38+
# with sigstore/fulcio when running outside of PRs.
39+
id-token: write
2740

2841
strategy:
2942
matrix:
@@ -46,6 +59,12 @@ jobs:
4659
runs-on: ${{ matrix.os }}
4760

4861
steps:
62+
# Docker is terrible and doesn't like uppercase image names.
63+
- name: Lowercase image name
64+
run: |
65+
IMAGE_NAME=$(echo ${IMAGE_NAME} | tr A-Z a-z)
66+
echo "IMAGE_NAME=${IMAGE_NAME}" >> "${GITHUB_ENV}"
67+
4968
- name: Check out the repo
5069
uses: actions/checkout@v6
5170

@@ -90,37 +109,99 @@ jobs:
90109
- name: Log in to registry
91110
uses: docker/login-action@v3
92111
with:
93-
registry: ghcr.io
112+
registry: ${{ env.REGISTRY }}
94113
username: ${{ github.actor }}
95114
password: ${{ secrets.GITHUB_TOKEN }}
96115

97-
- name: Extract metadata
98-
id: meta
99-
uses: docker/metadata-action@v5
100-
with:
101-
images: ghcr.io/${{ github.repository }}
102-
tags: |
103-
type=raw,value=${{ steps.pkg.outputs.name }}-julia${{ matrix.julia }}-cuda${{ steps.cuda.outputs.major }}
104-
type=raw,value=${{ steps.pkg.outputs.name }},enable=${{ matrix.default == true && (github.ref_type == 'tag' || inputs.tag != '') }}
105-
type=raw,value=latest,enable=${{ matrix.default == true && (github.ref_type == 'tag' || (inputs.tag != '' && inputs.mark_as_latest)) }}
106-
type=raw,value=dev,enable=${{ matrix.default == true && github.ref_type == 'branch' && inputs.tag == '' }}
107-
labels: |
108-
org.opencontainers.image.version=${{ steps.pkg.outputs.version }}
109-
110116
- name: Set up Docker Buildx
111117
uses: docker/setup-buildx-action@v3
112118

113-
- name: Build and push image
119+
- name: Build and push
120+
id: build
114121
uses: docker/build-push-action@v6
115122
with:
116123
context: .
117124
push: true
118125
provenance: false # the build fetches the repo again, so provenance tracking is not useful
119126
platforms: ${{ matrix.platform }}
120-
tags: ${{ steps.meta.outputs.tags }}
121-
labels: ${{ steps.meta.outputs.labels }}
127+
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.pkg.outputs.name }}-julia${{ matrix.julia }}-cuda${{ steps.cuda.outputs.major }}
128+
labels: |
129+
org.opencontainers.image.version=${{ steps.pkg.outputs.version }}
122130
build-args: |
123131
JULIA_VERSION=${{ matrix.julia }}
124132
CUDA_VERSION=${{ matrix.cuda }}
125133
PACKAGE_SPEC=CUDA#${{ steps.pkg.outputs.ref }}
126134
JULIA_CPU_TARGET=${{ steps.cpu_target.outputs.target }}
135+
136+
- name: Export digest
137+
id: export-digest
138+
run: |
139+
mkdir -p /tmp/digests
140+
digest_name=${{ steps.pkg.outputs.name }}-julia${{ matrix.julia }}-cuda${{ steps.cuda.outputs.major }}-$(echo ${{ matrix.platform }} | tr / -)
141+
echo "digest_name=${digest_name}" | tee "${GITHUB_OUTPUT}"
142+
echo "${{ steps.build.outputs.digest }}" > "/tmp/digests/${digest_name}"
143+
144+
- name: Upload digest
145+
uses: actions/upload-artifact@v6
146+
with:
147+
name: digests-${{ steps.export-digest.outputs.digest_name }}
148+
path: /tmp/digests/*
149+
if-no-files-found: error
150+
retention-days: 1
151+
152+
merge:
153+
needs: build
154+
runs-on: ubuntu-latest
155+
permissions:
156+
contents: read
157+
packages: write
158+
attestations: write
159+
# This is used to complete the identity challenge
160+
# with sigstore/fulcio when running outside of PRs.
161+
id-token: write
162+
if: github.event_name != 'pull_request'
163+
164+
steps:
165+
# Docker is terrible and doesn't like uppercase image names.
166+
- name: Lowercase image name
167+
run: |
168+
IMAGE_NAME=$(echo ${IMAGE_NAME} | tr A-Z a-z)
169+
echo "IMAGE_NAME=${IMAGE_NAME}" >> "${GITHUB_ENV}"
170+
171+
- name: Download digests
172+
uses: actions/download-artifact@v7
173+
with:
174+
path: /tmp/digests
175+
pattern: digests-*
176+
merge-multiple: true
177+
178+
# https://github.com/docker/setup-buildx-action
179+
- name: Set up Docker Buildx
180+
uses: docker/setup-buildx-action@v3
181+
182+
# Log into the registry.
183+
# https://github.com/docker/login-action
184+
- name: Log into registry
185+
uses: docker/login-action@v3
186+
with:
187+
registry: ${{ env.REGISTRY }}
188+
username: ${{ github.actor }}
189+
password: ${{ secrets.GITHUB_TOKEN }}
190+
191+
- name: Create manifest lists for each tag
192+
run: |
193+
for file in /tmp/digests/*; do
194+
TAG=${file##*/} # e.g. "dev-julia1.11-cuda11-linux-amd64"
195+
VARIANT=$(echo ${TAG} | cut -d- -f1-3) # e.g. "dev-julia1.11-cuda11"
196+
# buildx imagetools needs: -t registry/image:tag and sources
197+
SOURCES=""
198+
for f in /tmp/digests/${VARIANT}-*; do
199+
# each f contains a digest per arch
200+
DIG=$(cat "${f}")
201+
PLATFORM=${f##*/} # e.g. "docs-linux-amd64"
202+
SOURCES="${SOURCES} ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${DIG}"
203+
done
204+
docker buildx imagetools create \
205+
--tag ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${VARIANT} \
206+
${SOURCES}
207+
done

0 commit comments

Comments
 (0)