Skip to content

Commit b52cefd

Browse files
committed
GHA updates.
1 parent 1681467 commit b52cefd

File tree

1 file changed

+204
-128
lines changed

1 file changed

+204
-128
lines changed

.github/workflows/docker-build.yml

Lines changed: 204 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -15,185 +15,261 @@ concurrency:
1515
cancel-in-progress: true
1616

1717
jobs:
18-
build:
19-
runs-on: ${{ matrix.runner }}
20-
permissions:
21-
contents: read
22-
packages: write
23-
id-token: write
24-
strategy:
25-
fail-fast: false
26-
matrix:
27-
include:
28-
# Hub (amd64 + arm64)
29-
- id: hub
30-
repo: cogstacksystems/jupyter-hub
31-
dockerfile: Dockerfile_hub
32-
context: .
33-
runner: ubuntu-22.04
34-
platform: linux/amd64
35-
gpu_build: "false"
36-
- id: hub
37-
repo: cogstacksystems/jupyter-hub
38-
dockerfile: Dockerfile_hub
39-
context: .
40-
runner: ubuntu-22.04-arm
41-
platform: linux/arm64
42-
gpu_build: "false"
43-
44-
# Singleuser CPU (amd64 + arm64)
45-
- id: singleuser-cpu
46-
repo: cogstacksystems/jupyter-singleuser
47-
dockerfile: Dockerfile_singleuser
48-
context: .
49-
runner: ubuntu-22.04
50-
platform: linux/amd64
51-
gpu_build: "false"
52-
- id: singleuser-cpu
53-
repo: cogstacksystems/jupyter-singleuser
54-
dockerfile: Dockerfile_singleuser
55-
context: .
56-
runner: ubuntu-22.04-arm
57-
platform: linux/arm64
58-
gpu_build: "false"
59-
60-
# Singleuser GPU (amd64 only)
61-
- id: singleuser-gpu
62-
repo: cogstacksystems/jupyter-singleuser-gpu
63-
dockerfile: Dockerfile_singleuser
64-
context: .
65-
runner: ubuntu-22.04
66-
platform: linux/amd64
67-
gpu_build: "true"
68-
18+
# ---------- AMD64 ----------
19+
build-amd64:
20+
runs-on: ubuntu-22.04
21+
if: ${{ github.event_name != 'pull_request' }}
22+
outputs:
23+
hub_digest: ${{ steps.hub.outputs.digest }}
24+
su_digest: ${{ steps.su.outputs.digest }}
6925
steps:
7026
- uses: actions/checkout@v5
27+
with: { submodules: recursive, fetch-depth: 0 }
28+
- uses: docker/setup-buildx-action@v3
29+
30+
- name: Docker meta (hub)
31+
id: meta_hub
32+
uses: docker/metadata-action@v5
7133
with:
72-
submodules: recursive
73-
fetch-depth: 0
34+
images: cogstacksystems/jupyter-hub
35+
tags: |
36+
type=semver,pattern={{version}},prefix=v
37+
type=semver,pattern={{major}}.{{minor}},prefix=v
38+
type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v') }}
39+
type=ref,event=branch,enable=${{ github.event_name != 'pull_request' }}
40+
type=sha,format=short
7441
42+
- name: Docker meta (singleuser)
43+
id: meta_su
44+
uses: docker/metadata-action@v5
45+
with:
46+
images: cogstacksystems/jupyter-singleuser
47+
tags: |
48+
type=semver,pattern={{version}},prefix=v
49+
type=semver,pattern={{major}}.{{minor}},prefix=v
50+
type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v') }}
51+
type=ref,event=branch,enable=${{ github.event_name != 'pull_request' }}
52+
type=sha,format=short
53+
54+
- uses: docker/login-action@v3
55+
with:
56+
username: ${{ secrets.DOCKER_HUB_USERNAME }}
57+
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
58+
59+
- name: Build & push hub (amd64)
60+
id: hub
61+
uses: docker/build-push-action@v6
62+
with:
63+
context: .
64+
file: Dockerfile_hub
65+
platforms: linux/amd64
66+
build-args: |
67+
CPU_ARCHITECTURE=amd64
68+
GPU_BUILD=false
69+
tags: ${{ steps.meta_hub.outputs.tags }}
70+
labels: ${{ steps.meta_hub.outputs.labels }}
71+
cache-from: type=gha,scope=hub-amd64
72+
cache-to: type=gha,mode=max,scope=hub-amd64
73+
provenance: false
74+
push: true
75+
76+
- name: Build & push singleuser (amd64)
77+
id: su
78+
uses: docker/build-push-action@v6
79+
with:
80+
context: .
81+
file: Dockerfile_singleuser
82+
platforms: linux/amd64
83+
build-args: |
84+
CPU_ARCHITECTURE=amd64
85+
GPU_BUILD=false
86+
tags: ${{ steps.meta_su.outputs.tags }}
87+
labels: ${{ steps.meta_su.outputs.labels }}
88+
cache-from: type=gha,scope=singleuser-amd64
89+
cache-to: type=gha,mode=max,scope=singleuser-amd64
90+
provenance: false
91+
push: true
92+
93+
94+
# ---------- ARM64 ----------
95+
build-arm64:
96+
runs-on: ubuntu-22.04-arm
97+
if: ${{ github.event_name != 'pull_request' }}
98+
outputs:
99+
hub_digest: ${{ steps.hub.outputs.digest }}
100+
su_digest: ${{ steps.su.outputs.digest }}
101+
steps:
102+
- uses: actions/checkout@v5
75103
- uses: docker/setup-buildx-action@v3
76104

77-
# SAME TAGS FOR BOTH ARCH BUILDS
78-
- name: Docker meta
79-
id: meta
105+
- name: Docker meta (hub)
106+
id: meta_hub
107+
uses: docker/metadata-action@v5
108+
with:
109+
images: cogstacksystems/jupyter-hub
110+
tags: |
111+
type=semver,pattern={{version}},prefix=v
112+
type=semver,pattern={{major}}.{{minor}},prefix=v
113+
type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v') }}
114+
type=ref,event=branch,enable=${{ github.event_name != 'pull_request' }}
115+
type=sha,format=short
116+
117+
- name: Docker meta (singleuser)
118+
id: meta_su
80119
uses: docker/metadata-action@v5
81120
with:
82-
images: ${{ matrix.repo }}
121+
images: cogstacksystems/jupyter-singleuser
83122
tags: |
84-
# strip "v" from vX.Y.Z
85123
type=semver,pattern={{version}},prefix=v
86124
type=semver,pattern={{major}}.{{minor}},prefix=v
87-
# latest on main AND on tags
88125
type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v') }}
89-
# branches (non-PR)
90126
type=ref,event=branch,enable=${{ github.event_name != 'pull_request' }}
91-
# short sha
92127
type=sha,format=short
93128
94129
- uses: docker/login-action@v3
95-
if: ${{ github.event_name != 'pull_request' && github.actor != 'dependabot[bot]' }}
96130
with:
97131
username: ${{ secrets.DOCKER_HUB_USERNAME }}
98132
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
99133

100-
- name: Build & push (native arch)
101-
id: build
134+
- name: Build & push hub (arm64)
135+
id: hub
102136
uses: docker/build-push-action@v6
103137
with:
104-
context: ${{ matrix.context }}
105-
file: ${{ matrix.dockerfile }}
106-
platforms: ${{ matrix.platform }} # linux/amd64 or linux/arm64
138+
context: .
139+
file: Dockerfile_hub
140+
platforms: linux/arm64
107141
build-args: |
108-
CPU_ARCHITECTURE=${{ startsWith(matrix.platform, 'linux/arm64') && 'arm64' || 'amd64' }}
109-
GPU_BUILD=${{ matrix.gpu_build }}
110-
tags: ${{ steps.meta.outputs.tags }} # <-- identical tag list for both arches
111-
labels: |
112-
${{ steps.meta.outputs.labels }}
113-
org.opencontainers.image.title=${{ matrix.id }}
114-
cache-from: type=gha,scope=${{ matrix.id }}-${{ matrix.platform }}
115-
cache-to: type=gha,mode=max,scope=${{ matrix.id }}-${{ matrix.platform }}
142+
CPU_ARCHITECTURE=arm64
143+
GPU_BUILD=false
144+
tags: ${{ steps.meta_hub.outputs.tags }}
145+
labels: ${{ steps.meta_hub.outputs.labels }}
146+
cache-from: type=gha,scope=hub-arm64
147+
cache-to: type=gha,mode=max,scope=hub-arm64
116148
provenance: false
117-
push: ${{ github.event_name != 'pull_request' }}
149+
push: true
150+
151+
- name: Build & push singleuser (arm64)
152+
id: su
153+
uses: docker/build-push-action@v6
154+
with:
155+
context: .
156+
file: Dockerfile_singleuser
157+
platforms: linux/arm64
158+
build-args: |
159+
CPU_ARCHITECTURE=arm64
160+
GPU_BUILD=false
161+
tags: ${{ steps.meta_su.outputs.tags }}
162+
labels: ${{ steps.meta_su.outputs.labels }}
163+
cache-from: type=gha,scope=singleuser-arm64
164+
cache-to: type=gha,mode=max,scope=singleuser-arm64
165+
provenance: false
166+
push: true
118167

119-
# Record tag -> digest for this image + arch
120-
- name: Save digests for this arch
121-
if: ${{ github.event_name != 'pull_request' }}
122-
shell: bash
123-
run: |
124-
set -euo pipefail
125-
arch="${{ matrix.platform == 'linux/arm64' && 'arm64' || 'amd64' }}"
126-
: > "digests-${{ matrix.id }}-${arch}.txt"
127-
while IFS= read -r ref; do
128-
[[ -z "$ref" ]] && continue
129-
echo "$ref ${{ steps.build.outputs.digest }}" >> "digests-${{ matrix.id }}-${arch}.txt"
130-
done < <(printf "%s" "${{ steps.meta.outputs.tags }}")
131168

132-
- name: Upload digest artifact
133-
if: ${{ github.event_name != 'pull_request' }}
134-
uses: actions/upload-artifact@v4
169+
# ---------- GPU (unchanged, amd64-only) ----------
170+
build-gpu:
171+
runs-on: ubuntu-22.04
172+
if: ${{ github.event_name != 'pull_request' }}
173+
steps:
174+
- uses: actions/checkout@v5
175+
- uses: docker/setup-buildx-action@v3
176+
177+
- name: Docker meta (singleuser-gpu)
178+
id: meta_gpu
179+
uses: docker/metadata-action@v5
135180
with:
136-
name: digests-${{ matrix.id }}-${{ matrix.platform == 'linux/arm64' && 'arm64' || 'amd64' }}
137-
path: digests-${{ matrix.id }}-${{ matrix.platform == 'linux/arm64' && 'arm64' || 'amd64' }}.txt
181+
images: cogstacksystems/jupyter-singleuser-gpu
182+
tags: |
183+
type=semver,pattern={{version}},prefix=v
184+
type=semver,pattern={{major}}.{{minor}},prefix=v
185+
type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v') }}
186+
type=ref,event=branch,enable=${{ github.event_name != 'pull_request' }}
187+
type=sha,format=short
188+
189+
- uses: docker/login-action@v3
190+
with:
191+
username: ${{ secrets.DOCKER_HUB_USERNAME }}
192+
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
193+
194+
- name: Build & push singleuser GPU (amd64)
195+
uses: docker/build-push-action@v6
196+
with:
197+
context: .
198+
file: Dockerfile_singleuser
199+
platforms: linux/amd64
200+
build-args: |
201+
CPU_ARCHITECTURE=amd64
202+
GPU_BUILD=true
203+
tags: ${{ steps.meta_gpu.outputs.tags }}
204+
labels: ${{ steps.meta_gpu.outputs.labels }}
205+
cache-from: type=gha,scope=singleuser-gpu-amd64
206+
cache-to: type=gha,mode=max,scope=singleuser-gpu-amd64
207+
provenance: false
208+
push: true
138209

139210
manifest:
140211
runs-on: ubuntu-22.04
141-
needs: build
142212
if: ${{ github.event_name != 'pull_request' }}
143-
strategy:
144-
fail-fast: false
145-
matrix:
146-
include:
147-
- id: hub
148-
repo: cogstacksystems/jupyter-hub
149-
- id: singleuser-cpu
150-
repo: cogstacksystems/jupyter-singleuser
151-
213+
needs: [build-amd64, build-arm64]
152214
steps:
153215
- uses: docker/login-action@v3
154216
with:
155217
username: ${{ secrets.DOCKER_HUB_USERNAME }}
156218
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
157219

158-
# same tag list again
159-
- name: Docker meta
160-
id: meta
220+
# Recompute tags (must match both builds)
221+
- name: Docker meta (hub)
222+
id: meta_hub
161223
uses: docker/metadata-action@v5
162224
with:
163-
images: ${{ matrix.repo }}
225+
images: cogstacksystems/jupyter-hub
164226
tags: |
165227
type=semver,pattern={{version}},prefix=v
166228
type=semver,pattern={{major}}.{{minor}},prefix=v
167229
type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v') }}
168230
type=ref,event=branch,enable=${{ github.event_name != 'pull_request' }}
169231
type=sha,format=short
170232
171-
# pull in the two digest lists for this image id
172-
- name: Download digest artifacts (amd64)
173-
uses: actions/download-artifact@v4
174-
with:
175-
name: digests-${{ matrix.id }}-amd64
176-
path: .
177-
- name: Download digest artifacts (arm64)
178-
uses: actions/download-artifact@v4
233+
- name: Docker meta (singleuser)
234+
id: meta_su
235+
uses: docker/metadata-action@v5
179236
with:
180-
name: digests-${{ matrix.id }}-arm64
181-
path: .
237+
images: cogstacksystems/jupyter-singleuser
238+
tags: |
239+
type=semver,pattern={{version}},prefix=v
240+
type=semver,pattern={{major}}.{{minor}},prefix=v
241+
type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v') }}
242+
type=ref,event=branch,enable=${{ github.event_name != 'pull_request' }}
243+
type=sha,format=short
244+
245+
- name: Create hub multi-arch manifests
246+
shell: bash
247+
env:
248+
AMD64: ${{ needs.build-amd64.outputs.hub_digest }}
249+
ARM64: ${{ needs.build-arm64.outputs.hub_digest }}
250+
run: |
251+
set -euo pipefail
252+
while IFS= read -r ref; do
253+
[[ -z "$ref" ]] && continue
254+
img="${ref%%:*}"; tag="${ref#*:}"
255+
docker buildx imagetools create \
256+
--tag "$img:$tag" \
257+
"$img@${AMD64}" \
258+
"$img@${ARM64}"
259+
done < <(printf "%s" "${{ steps.meta_hub.outputs.tags }}")
182260
183-
- name: Create multi-arch manifests
261+
- name: Create singleuser multi-arch manifests
184262
shell: bash
263+
env:
264+
AMD64: ${{ needs.build-amd64.outputs.su_digest }}
265+
ARM64: ${{ needs.build-arm64.outputs.su_digest }}
185266
run: |
186267
set -euo pipefail
187268
while IFS= read -r ref; do
188269
[[ -z "$ref" ]] && continue
189-
image="${ref%%:*}"
190-
tag="${ref#*:}"
191-
amd64_d=$(awk -v r="$ref" '$1==r{print $2}' digests-${{ matrix.id }}-amd64.txt)
192-
arm64_d=$(awk -v r="$ref" '$1==r{print $2}' digests-${{ matrix.id }}-arm64.txt)
193-
[[ -z "$amd64_d" || -z "$arm64_d" ]] && { echo "skip $ref (missing digest)"; continue; }
194-
echo "⛵ $image:$tag"
270+
img="${ref%%:*}"; tag="${ref#*:}"
195271
docker buildx imagetools create \
196-
--tag "$image:$tag" \
197-
"$image@${amd64_d}" \
198-
"$image@${arm64_d}"
199-
done < <(printf "%s" "${{ steps.meta.outputs.tags }}")
272+
--tag "$img:$tag" \
273+
"$img@${AMD64}" \
274+
"$img@${ARM64}"
275+
done < <(printf "%s" "${{ steps.meta_su.outputs.tags }}")

0 commit comments

Comments
 (0)