Skip to content

Commit c8d5b06

Browse files
fl0rianrbetonme
andauthored
ci: add safe AMD64 and ARM64 container validation (#2637)
* ci: add safe AMD64 and ARM64 container validation Add native architecture builds, runtime smoke tests, and an optional ARM64 test artifact without modifying production image tags. Co-authored-by: betonme <942288+betonme@users.noreply.github.com> * Modify to create artifacts every time (temporary) * ci: remove temporary ARM64 artifact export --------- Co-authored-by: betonme <942288+betonme@users.noreply.github.com>
1 parent f59f263 commit c8d5b06

1 file changed

Lines changed: 146 additions & 0 deletions

File tree

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
# .github/workflows/container-build-test.yml
2+
3+
name: Container Build Tests
4+
5+
on:
6+
pull_request:
7+
paths:
8+
- Dockerfile
9+
- CMakeLists.txt
10+
- CMakePresets.json
11+
- cmake/**
12+
- src/cpp/**
13+
- src/web-app/**
14+
- .github/workflows/build-and-push-container.yml
15+
- .github/workflows/container-build-test.yml
16+
17+
workflow_dispatch:
18+
inputs:
19+
upload_arm64_artifact:
20+
description: Upload the ARM64 image for external testing
21+
type: boolean
22+
required: false
23+
default: false
24+
25+
permissions:
26+
contents: read
27+
28+
jobs:
29+
build-and-smoke-test:
30+
name: Build and smoke test (${{ matrix.arch }})
31+
32+
strategy:
33+
fail-fast: false
34+
matrix:
35+
include:
36+
- arch: amd64
37+
platform: linux/amd64
38+
runner: ubuntu-latest
39+
40+
- arch: arm64
41+
platform: linux/arm64
42+
runner: ubuntu-24.04-arm
43+
44+
runs-on: ${{ matrix.runner }}
45+
timeout-minutes: 90
46+
47+
steps:
48+
- name: Checkout repository
49+
uses: actions/checkout@v5
50+
51+
- name: Set up Docker Buildx
52+
uses: docker/setup-buildx-action@v3
53+
54+
- name: Build container
55+
uses: docker/build-push-action@v5
56+
with:
57+
context: .
58+
file: Dockerfile
59+
platforms: ${{ matrix.platform }}
60+
load: true
61+
push: false
62+
tags: lemonade-server:test-${{ matrix.arch }}
63+
cache-from: type=gha,scope=container-${{ matrix.arch }}
64+
cache-to: type=gha,mode=max,scope=container-${{ matrix.arch }}
65+
66+
- name: Verify image architecture
67+
shell: bash
68+
run: |
69+
set -euo pipefail
70+
71+
actual_arch="$(
72+
docker image inspect \
73+
"lemonade-server:test-${{ matrix.arch }}" \
74+
--format '{{.Architecture}}'
75+
)"
76+
77+
if [[ "${actual_arch}" != "${{ matrix.arch }}" ]]; then
78+
echo "Expected ${{ matrix.arch }}, got ${actual_arch}"
79+
exit 1
80+
fi
81+
82+
- name: Verify CLI starts
83+
run: |
84+
docker run --rm \
85+
"lemonade-server:test-${{ matrix.arch }}" \
86+
lemonade --help
87+
88+
- name: Start server
89+
run: |
90+
docker run --detach \
91+
--name lemonade-smoke \
92+
--publish 127.0.0.1:13305:13305 \
93+
"lemonade-server:test-${{ matrix.arch }}"
94+
95+
- name: Check server health
96+
shell: bash
97+
run: |
98+
set -euo pipefail
99+
100+
for attempt in $(seq 1 60); do
101+
if curl --fail --silent \
102+
http://127.0.0.1:13305/live \
103+
> /dev/null; then
104+
exit 0
105+
fi
106+
107+
sleep 2
108+
done
109+
110+
echo "Server failed to become healthy"
111+
docker logs lemonade-smoke
112+
exit 1
113+
114+
- name: Show server logs
115+
if: failure()
116+
run: docker logs lemonade-smoke || true
117+
118+
- name: Stop server
119+
if: always()
120+
run: docker rm --force lemonade-smoke || true
121+
122+
- name: Export ARM64 image
123+
if: >-
124+
matrix.arch == 'arm64' &&
125+
github.event_name == 'workflow_dispatch' &&
126+
inputs.upload_arm64_artifact
127+
shell: bash
128+
run: |
129+
set -euo pipefail
130+
131+
docker save "lemonade-server:test-arm64" \
132+
| gzip -1 \
133+
> lemonade-server-arm64.tar.gz
134+
135+
- name: Upload ARM64 test image
136+
if: >-
137+
matrix.arch == 'arm64' &&
138+
github.event_name == 'workflow_dispatch' &&
139+
inputs.upload_arm64_artifact
140+
uses: actions/upload-artifact@v4
141+
with:
142+
name: lemonade-server-arm64-${{ github.sha }}
143+
path: lemonade-server-arm64.tar.gz
144+
if-no-files-found: error
145+
retention-days: 7
146+
compression-level: 0

0 commit comments

Comments
 (0)