Skip to content

Commit 20cc85f

Browse files
committed
ci: speed up multi-arch publish and trigger Coolify deploy
Build amd64/arm64 on native runners, cache Docker layers per platform, and redeploy via WEBHOOK_URL after pushing to GHCR.
1 parent 2d9540b commit 20cc85f

2 files changed

Lines changed: 103 additions & 14 deletions

File tree

.github/workflows/publish.yml

Lines changed: 97 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,86 @@ on:
55
branches: [main]
66
tags: ["v*"]
77

8+
concurrency:
9+
group: publish-${{ github.ref }}
10+
cancel-in-progress: true
11+
812
env:
913
REGISTRY: ghcr.io
1014
IMAGE_NAME: ${{ github.repository }}
1115

1216
jobs:
13-
build-and-push:
14-
runs-on: ubuntu-latest
17+
build:
18+
strategy:
19+
fail-fast: false
20+
matrix:
21+
include:
22+
- platform: linux/amd64
23+
runner: ubuntu-latest
24+
- platform: linux/arm64
25+
runner: ubuntu-24.04-arm
26+
runs-on: ${{ matrix.runner }}
1527
permissions:
1628
contents: read
1729
packages: write
1830

1931
steps:
32+
- name: Prepare
33+
run: |
34+
platform=${{ matrix.platform }}
35+
echo "PLATFORM_PAIR=${platform//\//-}" >> "$GITHUB_ENV"
36+
2037
- uses: actions/checkout@v4
2138

22-
- uses: docker/setup-qemu-action@v3
39+
- uses: docker/setup-buildx-action@v3
40+
41+
- uses: docker/login-action@v3
42+
with:
43+
registry: ${{ env.REGISTRY }}
44+
username: ${{ github.actor }}
45+
password: ${{ secrets.GITHUB_TOKEN }}
46+
47+
- uses: docker/metadata-action@v5
48+
id: meta
49+
with:
50+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
51+
52+
- uses: docker/build-push-action@v6
53+
id: build
54+
with:
55+
context: .
56+
platforms: ${{ matrix.platform }}
57+
labels: ${{ steps.meta.outputs.labels }}
58+
outputs: type=image,name=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true
59+
cache-from: type=gha,scope=build-${{ env.PLATFORM_PAIR }}
60+
cache-to: type=gha,scope=build-${{ env.PLATFORM_PAIR }},mode=max
61+
62+
- name: Export digest
63+
run: |
64+
mkdir -p "${{ runner.temp }}/digests"
65+
digest="${{ steps.build.outputs.digest }}"
66+
touch "${{ runner.temp }}/digests/${digest#sha256:}"
67+
68+
- uses: actions/upload-artifact@v4
69+
with:
70+
name: digests-${{ env.PLATFORM_PAIR }}
71+
path: ${{ runner.temp }}/digests/*
72+
if-no-files-found: error
73+
retention-days: 1
74+
75+
merge:
76+
needs: build
77+
runs-on: ubuntu-latest
78+
permissions:
79+
contents: read
80+
packages: write
81+
82+
steps:
83+
- uses: actions/download-artifact@v4
84+
with:
85+
path: ${{ runner.temp }}/digests
86+
pattern: digests-*
87+
merge-multiple: true
2388

2489
- uses: docker/setup-buildx-action@v3
2590

@@ -39,12 +104,32 @@ jobs:
39104
type=semver,pattern={{version}}
40105
type=sha
41106
42-
- uses: docker/build-push-action@v6
43-
with:
44-
context: .
45-
platforms: linux/amd64,linux/arm64
46-
push: true
47-
tags: ${{ steps.meta.outputs.tags }}
48-
labels: ${{ steps.meta.outputs.labels }}
49-
cache-from: type=gha
50-
cache-to: type=gha,mode=max
107+
- name: Create manifest list and push
108+
working-directory: ${{ runner.temp }}/digests
109+
run: |
110+
docker buildx imagetools create \
111+
$(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
112+
$(printf '${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@sha256:%s ' *)
113+
114+
- name: Inspect image
115+
run: |
116+
docker buildx imagetools inspect \
117+
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.version }}
118+
119+
deploy:
120+
needs: merge
121+
if: github.ref == 'refs/heads/main'
122+
runs-on: ubuntu-latest
123+
steps:
124+
- name: Trigger deployment
125+
env:
126+
WEBHOOK_URL: ${{ secrets.WEBHOOK_URL }}
127+
WEBHOOK_TOKEN: ${{ secrets.WEBHOOK_TOKEN }}
128+
run: |
129+
if [ -z "$WEBHOOK_URL" ] || [ -z "$WEBHOOK_TOKEN" ]; then
130+
echo "WEBHOOK_URL / WEBHOOK_TOKEN secrets are not set; skipping deploy."
131+
exit 0
132+
fi
133+
curl --fail --show-error --silent \
134+
--request GET "$WEBHOOK_URL" \
135+
--header "Authorization: Bearer $WEBHOOK_TOKEN"

Dockerfile

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
# syntax=docker/dockerfile:1
2+
13
# Node 24 LTS (Alpine) — Next.js 16
24
FROM node:24-alpine AS base
35

@@ -7,7 +9,8 @@ RUN apk add --no-cache libc6-compat
79
WORKDIR /app
810

911
COPY package.json package-lock.json ./
10-
RUN npm ci
12+
RUN --mount=type=cache,target=/root/.npm \
13+
npm ci
1114

1215
# Rebuild the source code only when needed
1316
FROM base AS builder
@@ -18,7 +21,8 @@ COPY . .
1821
# Next.js expects ./public to exist; empty dirs often aren't in the image/context.
1922
RUN mkdir -p public
2023

21-
RUN npx next build --webpack
24+
RUN --mount=type=cache,target=/app/.next/cache \
25+
npx next build --webpack
2226

2327
# Production image
2428
FROM base AS runner

0 commit comments

Comments
 (0)