Skip to content

Commit 79a2909

Browse files
Merge branch 'main' into chore/phase1-a1
2 parents 4f27969 + 7ca2158 commit 79a2909

109 files changed

Lines changed: 16775 additions & 7666 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/docker-publish-calm-hub-native.yml

Lines changed: 139 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ on:
99
- main
1010
paths:
1111
- 'calm-hub/**'
12+
- 'calm-hub-ui/**'
1213
- '.github/workflows/docker-publish-calm-hub-native.yml'
1314
# Manual trigger from GitHub UI (allows custom tag)
1415
workflow_dispatch:
@@ -23,9 +24,24 @@ concurrency:
2324
cancel-in-progress: false
2425

2526
jobs:
26-
build-and-push:
27-
name: Build and Push Native Docker Image
28-
runs-on: ubuntu-latest
27+
# ── Per-architecture build, smoke test, and digest push ──────────────────
28+
# Each runner compiles the native binary for its own architecture (GraalVM
29+
# native binaries are arch-specific) via Quarkus container-build. After a
30+
# Docker smoke test the image is pushed to the registry by digest only (no
31+
# tag yet). Digests are uploaded as artifacts for the merge job.
32+
build:
33+
name: Build ${{ matrix.arch }}
34+
runs-on: ${{ matrix.runner }}
35+
strategy:
36+
fail-fast: false
37+
matrix:
38+
include:
39+
- arch: amd64
40+
runner: ubuntu-latest
41+
platform: linux/amd64
42+
- arch: arm64
43+
runner: ubuntu-24.04-arm
44+
platform: linux/arm64
2945

3046
steps:
3147
# Step 1: Checkout the repository
@@ -44,29 +60,131 @@ jobs:
4460
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5
4561
with:
4662
path: ~/.m2
47-
key: ${{ runner.os }}-m2-${{ hashFiles('calm-hub/pom.xml') }}
63+
key: ${{ runner.os }}-${{ matrix.arch }}-m2-${{ hashFiles('calm-hub/pom.xml') }}
4864
restore-keys: |
49-
${{ runner.os }}-m2-
65+
${{ runner.os }}-${{ matrix.arch }}-m2-
5066
51-
# Step 4: Compile the native binary via the shared build script.
52-
# --no-docker: skip the local docker build; this workflow uses buildx below
53-
# for the push. Quarkus pulls and runs the Mandrel builder container
54-
# (quarkus.native.container-build=true) to produce a linux/amd64 binary.
67+
# Step 4: Compile the native binary for this runner's architecture.
68+
# --no-docker: skip the local docker build; buildx handles the image below.
69+
# Quarkus pulls and runs the Mandrel builder container
70+
# (quarkus.native.container-build=true) to produce a native binary
71+
# targeting the runner's architecture.
5572
- name: Build native binary
5673
run: bash calm-hub/build-native-image.sh --no-docker
5774

5875
# Step 5: Set up Docker Buildx
5976
- name: Set up Docker Buildx
6077
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3
6178

62-
# Step 6: Login to Docker Hub
79+
# Step 6: Login to Docker Hub (required for the push-by-digest step)
80+
- name: Login to Docker Hub
81+
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3
82+
with:
83+
username: ${{ secrets.DOCKER_USERNAME }}
84+
password: ${{ secrets.DOCKER_PASSWORD }}
85+
86+
# Step 7: Build image locally for smoke testing.
87+
# load: true loads the image into the local Docker daemon (single-arch only).
88+
# cache-to populates the GHA layer cache scoped per-arch so the push step
89+
# below is a near-instant cache hit.
90+
- name: Build image for smoke test
91+
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6
92+
with:
93+
context: calm-hub
94+
file: calm-hub/src/main/docker/Dockerfile.native
95+
platforms: ${{ matrix.platform }}
96+
load: true
97+
tags: calm-hub:smoke
98+
cache-from: type=gha,scope=native-${{ matrix.arch }}
99+
cache-to: type=gha,mode=max,scope=native-${{ matrix.arch }}
100+
101+
# Step 8: Smoke test — start a transient MongoDB and the calm-hub container
102+
# on a private Docker network, run the smoke-test.sh assertions, then stop.
103+
# The test validates: GET /api/calm/namespaces -> 200 and POST -> 201 (writes
104+
# enabled; this is the writable MongoDB-backed image).
105+
# Auth is disabled for the smoke test (the prod image defaults to auth-on).
106+
- name: Smoke test
107+
run: |
108+
docker network create smoke-net
109+
docker run -d --name mongo --network smoke-net mongo:8
110+
docker run -d --name calmhub --network smoke-net \
111+
-p 8080:8080 \
112+
-e QUARKUS_MONGODB_CONNECTION_STRING=mongodb://mongo:27017 \
113+
-e CALM_AUTH_ENABLED=false \
114+
-e QUARKUS_OIDC_TENANT_ENABLED=false \
115+
calm-hub:smoke
116+
bash calm-hub/smoke-test.sh http://localhost:8080 readwrite
117+
118+
- name: Dump container logs on failure
119+
if: failure()
120+
run: docker logs calmhub 2>/dev/null || true
121+
122+
- name: Cleanup smoke test containers
123+
if: always()
124+
run: |
125+
docker rm -f calmhub mongo 2>/dev/null || true
126+
docker network rm smoke-net 2>/dev/null || true
127+
128+
# Produce labels without tags (only the merge job applies tags)
129+
- name: Extract Docker labels
130+
id: meta-labels
131+
uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5
132+
with:
133+
images: ${{ secrets.DOCKER_USERNAME }}/calm-hub
134+
135+
# Step 9: Push this architecture's image by digest (no tag).
136+
# Tags are applied in the merge job once both arch digests are available.
137+
# The GHA layer cache from step 7 (load) makes this build a cache hit.
138+
- name: Build and push by digest
139+
id: push
140+
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6
141+
with:
142+
context: calm-hub
143+
file: calm-hub/src/main/docker/Dockerfile.native
144+
platforms: ${{ matrix.platform }}
145+
outputs: type=image,name=${{ secrets.DOCKER_USERNAME }}/calm-hub,push-by-digest=true,name-canonical=true,push=true
146+
labels: ${{ steps.meta-labels.outputs.labels }}
147+
cache-from: type=gha,scope=native-${{ matrix.arch }}
148+
cache-to: type=gha,mode=max,scope=native-${{ matrix.arch }}
149+
150+
# Step 10: Export the pushed digest to a file for the merge job.
151+
- name: Export digest
152+
run: |
153+
mkdir -p /tmp/digests
154+
digest="${{ steps.push.outputs.digest }}"
155+
touch "/tmp/digests/${digest#sha256:}"
156+
157+
- name: Upload digest
158+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
159+
with:
160+
name: digests-native-${{ matrix.arch }}
161+
path: /tmp/digests/*
162+
if-no-files-found: error
163+
retention-days: 1
164+
165+
# ── Merge per-arch digests into a single multi-arch manifest ─────────────
166+
merge:
167+
name: Merge multi-arch manifest
168+
runs-on: ubuntu-latest
169+
needs: build
170+
171+
steps:
172+
- name: Download digests
173+
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
174+
with:
175+
path: /tmp/digests
176+
pattern: digests-native-*
177+
merge-multiple: true
178+
179+
- name: Set up Docker Buildx
180+
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3
181+
63182
- name: Login to Docker Hub
64183
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3
65184
with:
66185
username: ${{ secrets.DOCKER_USERNAME }}
67186
password: ${{ secrets.DOCKER_PASSWORD }}
68187

69-
# Step 7: Extract metadata for Docker
70188
- name: Extract Docker metadata
71189
id: meta
72190
uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5
@@ -77,17 +195,13 @@ jobs:
77195
type=sha,format=short,suffix=-native
78196
type=ref,event=tag,suffix=-native
79197
80-
# Step 8: Build and push the native image.
81-
# Native binaries are architecture-specific; the binary compiled above is
82-
# linux/amd64, so the image is published for linux/amd64 only.
83-
- name: Build and push
84-
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6
85-
with:
86-
context: calm-hub
87-
file: calm-hub/src/main/docker/Dockerfile.native
88-
platforms: linux/amd64
89-
push: true
90-
tags: ${{ steps.meta.outputs.tags }}
91-
labels: ${{ steps.meta.outputs.labels }}
92-
cache-from: type=gha
93-
cache-to: type=gha,mode=max
198+
# Assemble a multi-arch manifest from the per-arch digests and tag it.
199+
- name: Create multi-arch manifest
200+
working-directory: /tmp/digests
201+
run: |
202+
docker buildx imagetools create \
203+
$(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
204+
$(printf '${{ secrets.DOCKER_USERNAME }}/calm-hub@sha256:%s ' *)
205+
206+
- name: Inspect manifest
207+
run: docker buildx imagetools inspect ${{ secrets.DOCKER_USERNAME }}/calm-hub:${{ steps.meta.outputs.version }}

0 commit comments

Comments
 (0)