Skip to content

Commit 644af9f

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 644af9f

1 file changed

Lines changed: 101 additions & 14 deletions

File tree

.github/workflows/Container.yml

Lines changed: 101 additions & 14 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,105 @@ 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

97116
- name: Extract metadata
98117
id: meta
99118
uses: docker/metadata-action@v5
100119
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 }}
120+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
109121

110122
- name: Set up Docker Buildx
111123
uses: docker/setup-buildx-action@v3
112124

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

0 commit comments

Comments
 (0)