Skip to content

Commit be76942

Browse files
authored
ci: don't cancel a merged PR's build when merging the next (#26)
* ci: skip arm64 emulation on PR docker builds The workflow built linux/amd64,linux/arm64 on every PR, but arm64 runs under QEMU emulation on the amd64 runner (a Next.js pnpm build under emulation is very slow) and PRs never push the image. Build amd64 only on PRs for validation and keep multi-arch on push to main. GHA layer caching (type=gha, mode=max) was already in place; the cost was emulation on cache miss, not missing cache. Claude-Session: https://claude.ai/code/session_01WyN27fNj1sCLihdHERQLKh Signed-off-by: Kevin Su <pingsutw@apache.org> * ci: don't cancel main build runs when merging back-to-back PRs All pushes to main shared the concurrency group '<workflow>-refs/heads/main', so merging a second PR cancelled the first merge's in-progress build (observed on run 29362267088). Key push runs by github.sha so each merged PR gets its own group and runs to completion; PRs still group by number so stale PR runs are cancelled on new commits. Claude-Session: https://claude.ai/code/session_01WyN27fNj1sCLihdHERQLKh Signed-off-by: Kevin Su <pingsutw@apache.org> * ci: build both amd64 and arm64 on PRs too Revert the PR-only amd64 build; always build both platforms for validation. Claude-Session: https://claude.ai/code/session_01WyN27fNj1sCLihdHERQLKh Signed-off-by: Kevin Su <pingsutw@apache.org> * ci: build arches on native runners instead of QEMU The multi-arch build ran both platforms on the amd64 runner, so arm64 went through QEMU emulation. Under emulation the Next.js/SWC build hangs for hours (runs 29862466454 and 29874051988 sat in-progress ~3h). Build each arch on its own native runner in a matrix (ubuntu-latest + ubuntu-24.04-arm, free for public repos), push each by digest, then merge into one multi-arch manifest on push to main. Per-arch GHA cache scopes avoid cross-arch cache clobbering. Keeps building both amd64 and arm64. Claude-Session: https://claude.ai/code/session_01WyN27fNj1sCLihdHERQLKh Signed-off-by: Kevin Su <pingsutw@apache.org> * ci: push image on PR builds too Push the multi-arch image on PRs, not just main. Every build pushes an immutable ghcr tag <sha>; main also updates <latest> and PRs also get a moving pr-<number> tag so the current PR image is easy to deploy. Fork PRs get a read-only token and cannot push, but contributors push branches within this repo, so that path is unaffected. Claude-Session: https://claude.ai/code/session_01WyN27fNj1sCLihdHERQLKh Signed-off-by: Kevin Su <pingsutw@apache.org> --------- Signed-off-by: Kevin Su <pingsutw@apache.org>
1 parent f1b27b9 commit be76942

1 file changed

Lines changed: 87 additions & 15 deletions

File tree

.github/workflows/docker-build.yaml

Lines changed: 87 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,30 @@ on:
99
- main
1010

1111
concurrency:
12-
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
12+
# PRs group by number so a new push cancels the stale run. Pushes to main
13+
# group by commit SHA so each merged PR gets its own run that is never
14+
# cancelled by a later merge.
15+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
1316
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
1417

18+
env:
19+
IMAGE: ghcr.io/unionai-oss/flyteconsole-v2
20+
1521
jobs:
16-
docker-build:
17-
runs-on: ubuntu-latest
22+
# Build each architecture on its own native runner in parallel. This avoids
23+
# QEMU emulation, which makes the Next.js/SWC build hang for hours on arm64.
24+
build:
25+
strategy:
26+
fail-fast: false
27+
matrix:
28+
include:
29+
- platform: linux/amd64
30+
runner: ubuntu-latest
31+
arch: amd64
32+
- platform: linux/arm64
33+
runner: ubuntu-24.04-arm
34+
arch: arm64
35+
runs-on: ${{ matrix.runner }}
1836
permissions:
1937
contents: read
2038
packages: write
@@ -23,30 +41,84 @@ jobs:
2341
- name: Checkout
2442
uses: actions/checkout@v4
2543

26-
- name: Set up QEMU
27-
uses: docker/setup-qemu-action@v3
28-
2944
- name: Set up Docker Buildx
3045
uses: docker/setup-buildx-action@v3
3146

47+
# PRs from forks get a read-only GITHUB_TOKEN and cannot push; branches in
48+
# this repo can. Contributors push branches here, so this is fine.
3249
- name: Login to GHCR
33-
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
3450
uses: docker/login-action@v3
3551
with:
3652
registry: ghcr.io
3753
username: ${{ github.actor }}
3854
password: ${{ secrets.GITHUB_TOKEN }}
3955

40-
- name: Build and push
56+
- name: Build and push by digest
57+
id: build
4158
uses: docker/build-push-action@v6
4259
with:
4360
context: .
44-
platforms: linux/amd64,linux/arm64
45-
push: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
61+
platforms: ${{ matrix.platform }}
4662
build-args: |
4763
BUILDKITE_COMMIT=${{ github.sha }}
48-
tags: |
49-
ghcr.io/unionai-oss/flyteconsole-v2:latest
50-
ghcr.io/unionai-oss/flyteconsole-v2:${{ github.sha }}
51-
cache-from: type=gha
52-
cache-to: type=gha,mode=max
64+
outputs: type=image,name=${{ env.IMAGE }},push-by-digest=true,name-canonical=true,push=true
65+
cache-from: type=gha,scope=${{ matrix.arch }}
66+
cache-to: type=gha,mode=max,scope=${{ matrix.arch }}
67+
68+
- name: Export digest
69+
env:
70+
DIGEST: ${{ steps.build.outputs.digest }}
71+
run: |
72+
mkdir -p /tmp/digests
73+
touch "/tmp/digests/${DIGEST#sha256:}"
74+
75+
- name: Upload digest
76+
uses: actions/upload-artifact@v4
77+
with:
78+
name: digests-${{ matrix.arch }}
79+
path: /tmp/digests/*
80+
if-no-files-found: error
81+
retention-days: 1
82+
83+
# Combine the per-arch images (pushed by digest above) into one multi-arch
84+
# tag. Tags <sha> always; <latest> on main, pr-<number> on PRs.
85+
merge:
86+
runs-on: ubuntu-latest
87+
needs: build
88+
permissions:
89+
contents: read
90+
packages: write
91+
92+
steps:
93+
- name: Download digests
94+
uses: actions/download-artifact@v4
95+
with:
96+
path: /tmp/digests
97+
pattern: digests-*
98+
merge-multiple: true
99+
100+
- name: Set up Docker Buildx
101+
uses: docker/setup-buildx-action@v3
102+
103+
- name: Login to GHCR
104+
uses: docker/login-action@v3
105+
with:
106+
registry: ghcr.io
107+
username: ${{ github.actor }}
108+
password: ${{ secrets.GITHUB_TOKEN }}
109+
110+
- name: Create and push manifest list
111+
working-directory: /tmp/digests
112+
env:
113+
SHA: ${{ github.sha }}
114+
PR: ${{ github.event.pull_request.number }}
115+
IS_MAIN: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
116+
run: |
117+
tags=(-t "$IMAGE:$SHA")
118+
if [ "$IS_MAIN" = "true" ]; then
119+
tags+=(-t "$IMAGE:latest")
120+
elif [ -n "$PR" ]; then
121+
tags+=(-t "$IMAGE:pr-$PR")
122+
fi
123+
docker buildx imagetools create "${tags[@]}" \
124+
$(printf "$IMAGE@sha256:%s " *)

0 commit comments

Comments
 (0)