Skip to content

Commit 4fadfa9

Browse files
authored
ci: use native arm64 runners for multi-arch Docker builds (#531)
* ci: use native arm64 runners for multi-arch Docker builds Replace QEMU-emulated arm64 builds with native ubuntu-24.04-arm runners to dramatically speed up multi-arch Docker image builds. The UI (Next.js) build was taking 40+ minutes under QEMU; native builds should complete in under 10 minutes. Changes: - Split reusable workflow into parallel build (per-platform) + merge jobs - amd64 builds on ubuntu-latest, arm64 builds on ubuntu-24.04-arm - Merge job creates multi-arch manifest via docker buildx imagetools - Cache scopes split per platform to avoid cross-arch pollution - Add optional `file` input for custom Dockerfile paths - Refactor admin-release.yaml to reuse the shared workflow * ci: add actionlint workflow to validate GitHub Actions on PR * fix(ci): use correct actionlint installation method * fix(ci): use raven-actions/actionlint for workflow linting * fix(ci): resolve shellcheck SC2181 in security-reusable workflow
1 parent 404748f commit 4fadfa9

4 files changed

Lines changed: 90 additions & 77 deletions

File tree

.github/workflows/_reusable-docker-release.yaml

Lines changed: 60 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@ on:
1111
description: "Docker build context path (e.g. ./src/server/core)"
1212
required: true
1313
type: string
14+
file:
15+
description: "Dockerfile path (defaults to {context}/Dockerfile)"
16+
required: false
17+
type: string
18+
default: ""
1419
tag_prefix:
1520
description: "Git tag prefix (e.g. core/v)"
1621
required: true
@@ -29,14 +34,22 @@ permissions:
2934
packages: write
3035

3136
jobs:
32-
build-and-push:
33-
runs-on: ubuntu-latest
34-
timeout-minutes: 60
37+
build:
38+
runs-on: ${{ matrix.runner }}
39+
timeout-minutes: 30
40+
strategy:
41+
fail-fast: true
42+
matrix:
43+
include:
44+
- platform: linux/amd64
45+
runner: ubuntu-latest
46+
suffix: amd64
47+
- platform: linux/arm64
48+
runner: ubuntu-24.04-arm
49+
suffix: arm64
3550
steps:
3651
- name: Checkout
3752
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
38-
with:
39-
fetch-depth: 0
4053

4154
- name: Log in to GitHub Container Registry
4255
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2
@@ -45,33 +58,64 @@ jobs:
4558
username: ${{ github.repository_owner }}
4659
password: ${{ secrets.GITHUB_TOKEN }}
4760

61+
- name: Set up Docker Buildx
62+
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd
63+
4864
- name: Extract metadata (tags, labels) for Docker
4965
id: meta
5066
uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf
5167
with:
5268
images: ghcr.io/memodb-io/${{ inputs.image_name }}
5369
tags: |
5470
type=sha
55-
type=semver,pattern={{version}},match=${{ inputs.tag_prefix }}(\d+\.\d+\.\d+)$
56-
57-
- name: Set up QEMU
58-
uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a
59-
60-
- name: Set up Docker Buildx
61-
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd
6271
6372
- name: Build and Push Docker image
6473
uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294
6574
with:
66-
platforms: linux/amd64,linux/arm64
75+
platforms: ${{ matrix.platform }}
6776
context: ${{ inputs.context }}
77+
file: ${{ inputs.file || '' }}
6878
push: true
69-
tags: ${{ steps.meta.outputs.tags }}
79+
tags: ghcr.io/memodb-io/${{ inputs.image_name }}:sha-${{ github.sha }}-${{ matrix.suffix }}
7080
labels: ${{ steps.meta.outputs.labels }}
7181
sbom: true
7282
provenance: mode=max
73-
cache-from: type=gha,scope=${{ inputs.image_name }}
74-
cache-to: type=gha,mode=max,scope=${{ inputs.image_name }}
83+
cache-from: type=gha,scope=${{ inputs.image_name }}-${{ matrix.suffix }}
84+
cache-to: type=gha,mode=max,scope=${{ inputs.image_name }}-${{ matrix.suffix }}
85+
86+
merge:
87+
runs-on: ubuntu-latest
88+
timeout-minutes: 10
89+
needs: build
90+
steps:
91+
- name: Checkout
92+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
93+
with:
94+
fetch-depth: 0
95+
96+
- name: Log in to GitHub Container Registry
97+
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2
98+
with:
99+
registry: ghcr.io
100+
username: ${{ github.repository_owner }}
101+
password: ${{ secrets.GITHUB_TOKEN }}
102+
103+
- name: Extract version from tag
104+
id: version
105+
run: |
106+
VERSION="${GITHUB_REF_NAME#${{ inputs.tag_prefix }}}"
107+
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
108+
109+
- name: Create multi-arch manifest
110+
run: |
111+
IMAGE="ghcr.io/memodb-io/${{ inputs.image_name }}"
112+
SHA_SHORT="$(echo "$GITHUB_SHA" | head -c 7)"
113+
114+
docker buildx imagetools create \
115+
--tag "${IMAGE}:${{ steps.version.outputs.version }}" \
116+
--tag "${IMAGE}:sha-${SHA_SHORT}" \
117+
"${IMAGE}:sha-${GITHUB_SHA}-amd64" \
118+
"${IMAGE}:sha-${GITHUB_SHA}-arm64"
75119
76120
- name: Generate Changelog
77121
run: |

.github/workflows/admin-release.yaml

Lines changed: 9 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -10,61 +10,12 @@ permissions:
1010
packages: write
1111

1212
jobs:
13-
build-and-push:
14-
runs-on: ubuntu-latest
15-
timeout-minutes: 60
16-
steps:
17-
- name: Checkout
18-
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
19-
with:
20-
fetch-depth: 0
21-
22-
- name: Log in to GitHub Container Registry
23-
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2
24-
with:
25-
registry: ghcr.io
26-
username: ${{ github.repository_owner }}
27-
password: ${{ secrets.GITHUB_TOKEN }}
28-
29-
- name: Extract metadata (tags, labels) for Docker
30-
id: meta
31-
uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf
32-
with:
33-
images: ghcr.io/memodb-io/acontext-admin
34-
tags: |
35-
type=sha
36-
type=semver,pattern={{version}},match=admin/v(\d+\.\d+\.\d+)$
37-
38-
- name: Set up QEMU
39-
uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a
40-
41-
- name: Set up Docker Buildx
42-
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd
43-
44-
- name: Build and Push Docker image
45-
uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294
46-
with:
47-
platforms: linux/amd64,linux/arm64
48-
context: ./src/server/api/go
49-
file: ./src/server/api/go/Dockerfile.admin
50-
push: true
51-
tags: ${{ steps.meta.outputs.tags }}
52-
labels: ${{ steps.meta.outputs.labels }}
53-
sbom: true
54-
provenance: mode=max
55-
cache-from: type=gha,scope=acontext-admin
56-
cache-to: type=gha,mode=max,scope=acontext-admin
57-
58-
- name: Generate Changelog
59-
run: |
60-
bash .github/scripts/generate-changelog.sh \
61-
--tag-prefix "admin/v" \
62-
--source-dir "src/server/api/go" \
63-
--display-name "Admin API" \
64-
--output "$GITHUB_WORKSPACE-CHANGELOG.txt" \
65-
--footer "Published to https://github.com/memodb-io/Acontext/pkgs/container/acontext-admin"
66-
67-
- name: Create Release
68-
uses: softprops/action-gh-release@153bb8e04406b158c6c84fc1615b65b24149a1fe
69-
with:
70-
body_path: ${{ github.workspace }}-CHANGELOG.txt
13+
release:
14+
uses: ./.github/workflows/_reusable-docker-release.yaml
15+
with:
16+
image_name: acontext-admin
17+
context: ./src/server/api/go
18+
file: ./src/server/api/go/Dockerfile.admin
19+
tag_prefix: "admin/v"
20+
display_name: Admin API
21+
source_dir: src/server/api/go
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
name: Lint Workflows
2+
3+
on:
4+
pull_request:
5+
paths:
6+
- ".github/workflows/**"
7+
8+
jobs:
9+
actionlint:
10+
runs-on: ubuntu-latest
11+
timeout-minutes: 5
12+
steps:
13+
- name: Checkout
14+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
15+
16+
- name: Run actionlint
17+
uses: raven-actions/actionlint@v2

.github/workflows/security-reusable.yaml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ jobs:
6060
uv export --format requirements-txt --no-hashes --no-dev > reqs.txt
6161
# Run pip-audit in JSON mode; filter out vulnerabilities with no fix available
6262
pip-audit -r reqs.txt -f json -o audit.json || true
63-
python3 -c "
63+
if python3 -c "
6464
import json, sys
6565
data = json.load(open('audit.json'))
6666
fixable = [v for dep in data.get('dependencies', [])
@@ -71,12 +71,13 @@ jobs:
7171
print(f\" {v['id']}: fix available -> {v['fix_versions']}\", file=sys.stderr)
7272
sys.exit(1)
7373
"
74-
if [ $? -ne 0 ]; then
74+
then
75+
echo "✅ $dir clean (unfixed-only vulnerabilities ignored)"
76+
else
7577
echo "❌ Fixable vulnerabilities found in $dir"
7678
rm -f reqs.txt audit.json
7779
exit 1
7880
fi
79-
echo "✅ $dir clean (unfixed-only vulnerabilities ignored)"
8081
rm -f reqs.txt audit.json
8182
cd - > /dev/null
8283
done

0 commit comments

Comments
 (0)