Skip to content

Commit 5320dd4

Browse files
authored
Merge pull request #142 from vcon-dev/feat/multi-arch-builds
Build multi-arch Docker images (linux/amd64 + linux/arm64)
2 parents 4b212f6 + a9ca714 commit 5320dd4

File tree

1 file changed

+117
-74
lines changed

1 file changed

+117
-74
lines changed
Lines changed: 117 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,35 @@
11
name: Build and Push Docker image
22

33
# CalVer Release Workflow
4-
#
4+
#
55
# Automatically creates a CalVer release on every push to main.
66
# Version format: YYYY.MM.DD (e.g., 2026.01.16)
77
# If multiple releases happen on the same day, adds sequence: YYYY.MM.DD.2, YYYY.MM.DD.3, etc.
88
#
9-
# Docker tags created:
10-
# - CalVer tag (e.g., 2026.01.16)
9+
# Build strategy: native runners (no QEMU) for maximum speed
10+
# amd64 builds on ubuntu-latest
11+
# arm64 builds on ubuntu-24.04-arm
12+
#
13+
# Docker tags created (linux/amd64 + linux/arm64 multi-arch manifest):
14+
# - CalVer tag (e.g., 2026.01.16) [main only]
15+
# - latest [main only]
1116
# - Branch name (e.g., main)
12-
# - Git short hash (e.g., main-a1b2c3d)
13-
# - latest (for main branch only)
17+
# - Branch + short sha (e.g., main-a1b2c3d)
1418

1519
on:
1620
push:
1721
branches: [main, release-test]
1822
tags: ['v*']
1923

2024
jobs:
21-
build:
25+
prepare:
2226
runs-on: ubuntu-latest
2327
permissions:
24-
contents: write # Need write for creating tags
25-
packages: write
28+
contents: write # needed to create git tags
29+
outputs:
30+
version: ${{ steps.calver.outputs.version }}
31+
short_sha: ${{ steps.git.outputs.short_sha }}
32+
build_time: ${{ steps.git.outputs.build_time }}
2633

2734
steps:
2835
- name: Checkout code
@@ -33,50 +40,38 @@ jobs:
3340
- name: Generate CalVer version
3441
id: calver
3542
run: |
36-
# Get today's date in YYYY.MM.DD format
3743
TODAY=$(date +"%Y.%m.%d")
38-
39-
# Get all existing tags for today
4044
EXISTING_TAGS=$(git tag -l "${TODAY}*" | sort -V)
41-
45+
4246
if [ -z "$EXISTING_TAGS" ]; then
43-
# No tags for today, use base date
4447
VERSION="${TODAY}"
4548
else
46-
# Find the highest sequence number
4749
LAST_TAG=$(echo "$EXISTING_TAGS" | tail -1)
48-
4950
if [[ "$LAST_TAG" == "$TODAY" ]]; then
50-
# First tag was just the date, next is .2
5151
VERSION="${TODAY}.2"
5252
elif [[ "$LAST_TAG" =~ ^${TODAY}\.([0-9]+)$ ]]; then
53-
# Extract sequence number and increment
5453
SEQ="${BASH_REMATCH[1]}"
55-
NEXT_SEQ=$((SEQ + 1))
56-
VERSION="${TODAY}.${NEXT_SEQ}"
54+
VERSION="${TODAY}.$((SEQ + 1))"
5755
else
58-
# Fallback
5956
VERSION="${TODAY}.2"
6057
fi
6158
fi
62-
59+
6360
echo "version=${VERSION}" >> $GITHUB_OUTPUT
6461
echo "Generated CalVer version: ${VERSION}"
6562
6663
- name: Get git commit info
6764
id: git
6865
run: |
6966
echo "short_sha=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
70-
echo "full_sha=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT
7167
echo "build_time=$(date -u +"%Y-%m-%dT%H:%M:%SZ")" >> $GITHUB_OUTPUT
7268
7369
- name: Create git tag
7470
if: github.ref == 'refs/heads/main'
7571
run: |
7672
git config user.name "github-actions[bot]"
7773
git config user.email "github-actions[bot]@users.noreply.github.com"
78-
79-
# Check if tag already exists
74+
8075
if git rev-parse "${{ steps.calver.outputs.version }}" >/dev/null 2>&1; then
8176
echo "Tag ${{ steps.calver.outputs.version }} already exists, skipping"
8277
else
@@ -85,6 +80,26 @@ jobs:
8580
echo "Created and pushed tag ${{ steps.calver.outputs.version }}"
8681
fi
8782
83+
build:
84+
needs: prepare
85+
runs-on: ${{ matrix.runner }}
86+
permissions:
87+
contents: read
88+
packages: write
89+
strategy:
90+
matrix:
91+
include:
92+
- platform: linux/amd64
93+
platform_tag: amd64
94+
runner: ubuntu-latest
95+
- platform: linux/arm64
96+
platform_tag: arm64
97+
runner: ubuntu-24.04-arm
98+
99+
steps:
100+
- name: Checkout code
101+
uses: actions/checkout@v4
102+
88103
- name: Set up Docker Buildx
89104
uses: docker/setup-buildx-action@v3
90105

@@ -95,67 +110,94 @@ jobs:
95110
username: ${{ secrets.AWS_ACCESS_KEY }}
96111
password: ${{ secrets.AWS_SECRET }}
97112

98-
- name: Extract metadata
99-
id: meta
100-
uses: docker/metadata-action@v5
101-
with:
102-
images: |
103-
public.ecr.aws/r4g1k2s3/vcon-dev/vcon-server
104-
tags: |
105-
# CalVer tag (e.g., 2026.01.16)
106-
type=raw,value=${{ steps.calver.outputs.version }},enable=${{ github.ref == 'refs/heads/main' }}
107-
# Branch name
108-
type=ref,event=branch
109-
# PR number
110-
type=ref,event=pr
111-
# Semver tags (for manual v* tags)
112-
type=semver,pattern={{version}}
113-
type=semver,pattern={{major}}.{{minor}}
114-
# Git sha with branch prefix
115-
type=sha,prefix={{branch}}-
116-
# Latest tag for main branch
117-
type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }}
118-
119-
- name: Build and push Docker image
113+
- name: Build and push (${{ matrix.platform_tag }})
120114
uses: docker/build-push-action@v5
121115
with:
122116
context: .
123117
file: ./docker/Dockerfile
124-
platforms: linux/amd64
118+
platforms: ${{ matrix.platform }}
125119
push: true
126-
cache-from: type=gha
127-
cache-to: type=gha,mode=max
128-
tags: ${{ steps.meta.outputs.tags }}
129-
labels: ${{ steps.meta.outputs.labels }}
120+
cache-from: type=gha,scope=vcon-server-${{ matrix.platform_tag }}
121+
cache-to: type=gha,mode=max,scope=vcon-server-${{ matrix.platform_tag }}
122+
tags: public.ecr.aws/r4g1k2s3/vcon-dev/vcon-server:${{ github.ref_name }}-${{ matrix.platform_tag }}
130123
build-args: |
131-
VCON_SERVER_VERSION=${{ steps.calver.outputs.version }}
132-
VCON_SERVER_GIT_COMMIT=${{ steps.git.outputs.short_sha }}
133-
VCON_SERVER_BUILD_TIME=${{ steps.git.outputs.build_time }}
124+
VCON_SERVER_VERSION=${{ needs.prepare.outputs.version }}
125+
VCON_SERVER_GIT_COMMIT=${{ needs.prepare.outputs.short_sha }}
126+
VCON_SERVER_BUILD_TIME=${{ needs.prepare.outputs.build_time }}
127+
128+
merge:
129+
needs: [prepare, build]
130+
runs-on: ubuntu-latest
131+
permissions:
132+
contents: read
133+
packages: write
134+
135+
steps:
136+
- name: Set up Docker Buildx
137+
uses: docker/setup-buildx-action@v3
134138

139+
- name: Log in to Amazon ECR Public
140+
uses: docker/login-action@v3
141+
with:
142+
registry: public.ecr.aws
143+
username: ${{ secrets.AWS_ACCESS_KEY }}
144+
password: ${{ secrets.AWS_SECRET }}
145+
146+
- name: Create multi-arch manifests
147+
env:
148+
IMAGE: public.ecr.aws/r4g1k2s3/vcon-dev/vcon-server
149+
VERSION: ${{ needs.prepare.outputs.version }}
150+
SHORT_SHA: ${{ needs.prepare.outputs.short_sha }}
151+
BRANCH: ${{ github.ref_name }}
152+
run: |
153+
AMD64="${IMAGE}:${BRANCH}-amd64"
154+
ARM64="${IMAGE}:${BRANCH}-arm64"
155+
156+
# Branch tag (always)
157+
docker buildx imagetools create --tag "${IMAGE}:${BRANCH}" "${AMD64}" "${ARM64}"
158+
159+
# Branch + sha tag (always)
160+
docker buildx imagetools create --tag "${IMAGE}:${BRANCH}-${SHORT_SHA}" "${AMD64}" "${ARM64}"
161+
162+
# CalVer and latest (main only)
163+
if [ "${BRANCH}" = "main" ]; then
164+
docker buildx imagetools create --tag "${IMAGE}:${VERSION}" "${AMD64}" "${ARM64}"
165+
docker buildx imagetools create --tag "${IMAGE}:latest" "${AMD64}" "${ARM64}"
166+
fi
167+
168+
release:
169+
needs: [prepare, merge]
170+
runs-on: ubuntu-latest
171+
if: github.ref == 'refs/heads/main'
172+
permissions:
173+
contents: write
174+
175+
steps:
135176
- name: Create GitHub Release
136-
if: github.ref == 'refs/heads/main'
137177
uses: softprops/action-gh-release@v1
138178
with:
139-
tag_name: ${{ steps.calver.outputs.version }}
140-
name: Release ${{ steps.calver.outputs.version }}
179+
tag_name: ${{ needs.prepare.outputs.version }}
180+
name: Release ${{ needs.prepare.outputs.version }}
141181
body: |
142-
## Release ${{ steps.calver.outputs.version }}
143-
144-
**Commit:** ${{ steps.git.outputs.short_sha }}
145-
**Build Time:** ${{ steps.git.outputs.build_time }}
146-
182+
## Release ${{ needs.prepare.outputs.version }}
183+
184+
**Commit:** ${{ needs.prepare.outputs.short_sha }}
185+
**Build Time:** ${{ needs.prepare.outputs.build_time }}
186+
147187
### Docker Images
148-
188+
189+
Both `linux/amd64` and `linux/arm64` are supported.
190+
149191
Pull using CalVer:
150192
```bash
151-
docker pull public.ecr.aws/r4g1k2s3/vcon-dev/vcon-server:${{ steps.calver.outputs.version }}
193+
docker pull public.ecr.aws/r4g1k2s3/vcon-dev/vcon-server:${{ needs.prepare.outputs.version }}
152194
```
153-
195+
154196
Pull using git hash:
155197
```bash
156-
docker pull public.ecr.aws/r4g1k2s3/vcon-dev/vcon-server:main-${{ steps.git.outputs.short_sha }}
198+
docker pull public.ecr.aws/r4g1k2s3/vcon-dev/vcon-server:main-${{ needs.prepare.outputs.short_sha }}
157199
```
158-
200+
159201
Pull latest:
160202
```bash
161203
docker pull public.ecr.aws/r4g1k2s3/vcon-dev/vcon-server:latest
@@ -171,12 +213,13 @@ jobs:
171213
echo "" >> $GITHUB_STEP_SUMMARY
172214
echo "| Property | Value |" >> $GITHUB_STEP_SUMMARY
173215
echo "|----------|-------|" >> $GITHUB_STEP_SUMMARY
174-
echo "| **Version** | ${{ steps.calver.outputs.version }} |" >> $GITHUB_STEP_SUMMARY
175-
echo "| **Git Commit** | ${{ steps.git.outputs.short_sha }} |" >> $GITHUB_STEP_SUMMARY
176-
echo "| **Build Time** | ${{ steps.git.outputs.build_time }} |" >> $GITHUB_STEP_SUMMARY
216+
echo "| **Version** | ${{ needs.prepare.outputs.version }} |" >> $GITHUB_STEP_SUMMARY
217+
echo "| **Git Commit** | ${{ needs.prepare.outputs.short_sha }} |" >> $GITHUB_STEP_SUMMARY
218+
echo "| **Build Time** | ${{ needs.prepare.outputs.build_time }} |" >> $GITHUB_STEP_SUMMARY
177219
echo "| **Branch** | ${{ github.ref_name }} |" >> $GITHUB_STEP_SUMMARY
178220
echo "" >> $GITHUB_STEP_SUMMARY
179-
echo "### Docker Tags" >> $GITHUB_STEP_SUMMARY
180-
echo '```' >> $GITHUB_STEP_SUMMARY
181-
echo "${{ steps.meta.outputs.tags }}" >> $GITHUB_STEP_SUMMARY
182-
echo '```' >> $GITHUB_STEP_SUMMARY
221+
echo "### Docker Tags (linux/amd64 + linux/arm64)" >> $GITHUB_STEP_SUMMARY
222+
echo "- \`${{ needs.prepare.outputs.version }}\`" >> $GITHUB_STEP_SUMMARY
223+
echo "- \`latest\`" >> $GITHUB_STEP_SUMMARY
224+
echo "- \`main\`" >> $GITHUB_STEP_SUMMARY
225+
echo "- \`main-${{ needs.prepare.outputs.short_sha }}\`" >> $GITHUB_STEP_SUMMARY

0 commit comments

Comments
 (0)