44 push :
55 branches : [main, master]
66 workflow_dispatch :
7- inputs :
8- dry-run :
9- description : " Run in dry-run mode (no actual release)"
10- required : false
11- default : " false"
12- type : choice
13- options :
14- - " true"
15- - " false"
167
178permissions :
189 contents : write
1910 packages : write
20- issues : write
21- pull-requests : write
2211 id-token : write
2312
2413env :
2514 GO_VERSION : " 1.26"
15+ NODE_VERSION : " 22"
16+ REGISTRY_IMAGE : ghcr.io/${{ github.repository_owner }}/gavel
2617
2718jobs :
2819 tag :
4031 tools : |
4132 svu
4233 GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
34+
4335 - id : tag
4436 run : |
4537 next=$(svu patch)
@@ -54,55 +46,229 @@ jobs:
5446 echo "tag=$next" >> "$GITHUB_OUTPUT"
5547 echo "created=true" >> "$GITHUB_OUTPUT"
5648
57- goreleaser :
58- name : GoReleaser
49+ build-binaries :
50+ name : Build ${{ matrix.goos }}/${{ matrix.goarch }}
5951 needs : tag
6052 if : needs.tag.outputs.created == 'true'
61- runs-on : ubuntu-latest
53+ runs-on : ${{ matrix.runner }}
54+ strategy :
55+ fail-fast : false
56+ matrix :
57+ include :
58+ - { goos: linux, goarch: amd64, runner: ubuntu-latest, archive: tar.gz, os_name: Linux, arch_name: x86_64 }
59+ - { goos: linux, goarch: arm64, runner: ubuntu-24.04-arm, archive: tar.gz, os_name: Linux, arch_name: arm64 }
60+ - { goos: darwin, goarch: amd64, runner: macos-13, archive: tar.gz, os_name: Darwin, arch_name: x86_64 }
61+ - { goos: darwin, goarch: arm64, runner: macos-latest, archive: tar.gz, os_name: Darwin, arch_name: arm64 }
62+ - { goos: windows, goarch: amd64, runner: ubuntu-latest, archive: zip, os_name: Windows, arch_name: x86_64 }
6263 steps :
63- - name : Checkout
64- uses : actions/checkout@v4
64+ - uses : actions/checkout@v4
6565 with :
66- fetch-depth : 0
6766 ref : ${{ needs.tag.outputs.tag }}
67+ fetch-depth : 0
6868
69- - name : Fetch tags
70- run : git fetch --force --tags
71-
72- - name : Set up Go
73- uses : actions/setup-go@v5
69+ - uses : actions/setup-go@v5
7470 with :
7571 go-version : ${{ env.GO_VERSION }}
7672 cache : true
7773
78- - name : Set up Node.js
79- uses : actions/setup-node@v4
74+ - uses : actions/setup-node@v4
8075 with :
81- node-version : ' 22'
76+ node-version : ${{ env.NODE_VERSION }}
77+ cache : npm
78+ cache-dependency-path : |
79+ testrunner/ui/package-lock.json
80+ pr/ui/package-lock.json
81+
82+ - name : Build testrunner UI
83+ run : |
84+ cd testrunner/ui
85+ npm ci
86+ npm run build
8287
83- - name : Install dependencies
88+ - name : Build PR UI
8489 run : |
85- go mod download
86- go mod tidy
90+ cd pr/ui
91+ npm ci
92+ npm run build
93+
94+ - name : Build binary
95+ env :
96+ GOOS : ${{ matrix.goos }}
97+ GOARCH : ${{ matrix.goarch }}
98+ CGO_ENABLED : " 0"
99+ TAG : ${{ needs.tag.outputs.tag }}
100+ run : |
101+ mkdir -p dist
102+ bin_name=gavel
103+ if [ "${{ matrix.goos }}" = "windows" ]; then
104+ bin_name=gavel.exe
105+ fi
106+ build_date=$(date -u +%Y-%m-%dT%H:%M:%SZ)
107+ go build -trimpath \
108+ -ldflags "-s -w -X main.version=${TAG} -X main.commit=${{ github.sha }} -X main.date=${build_date}" \
109+ -o "dist/${bin_name}" \
110+ ./cmd/gavel
111+
112+ - name : Archive binary
113+ id : archive
114+ env :
115+ TAG : ${{ needs.tag.outputs.tag }}
116+ run : |
117+ cd dist
118+ archive_name="gavel_${{ matrix.os_name }}_${{ matrix.arch_name }}"
119+ if [ "${{ matrix.archive }}" = "zip" ]; then
120+ zip "${archive_name}.zip" gavel.exe
121+ echo "path=dist/${archive_name}.zip" >> "$GITHUB_OUTPUT"
122+ else
123+ tar -czf "${archive_name}.tar.gz" gavel
124+ echo "path=dist/${archive_name}.tar.gz" >> "$GITHUB_OUTPUT"
125+ fi
87126
88- - name : Set up QEMU
89- uses : docker/setup-qemu-action@v3
127+ - uses : actions/upload-artifact@v4
128+ with :
129+ name : binary-${{ matrix.goos }}-${{ matrix.goarch }}
130+ path : ${{ steps.archive.outputs.path }}
131+ if-no-files-found : error
132+ retention-days : 1
133+
134+ build-docker :
135+ name : Build image ${{ matrix.platform }}
136+ needs : [tag, build-binaries]
137+ if : needs.tag.outputs.created == 'true'
138+ runs-on : ${{ matrix.runner }}
139+ strategy :
140+ fail-fast : false
141+ matrix :
142+ include :
143+ - { platform: linux/amd64, runner: ubuntu-latest, goarch: amd64, pair: linux-amd64 }
144+ - { platform: linux/arm64, runner: ubuntu-24.04-arm, goarch: arm64, pair: linux-arm64 }
145+ steps :
146+ - uses : actions/checkout@v4
147+ with :
148+ ref : ${{ needs.tag.outputs.tag }}
149+
150+ - name : Download linux binary
151+ uses : actions/download-artifact@v4
152+ with :
153+ name : binary-linux-${{ matrix.goarch }}
154+ path : .
155+
156+ - name : Extract binary
157+ run : |
158+ tar -xzf "gavel_Linux_$( [ "${{ matrix.goarch }}" = "amd64" ] && echo x86_64 || echo arm64 ).tar.gz"
159+ chmod +x gavel
160+ ls -l gavel
90161
91- - name : Set up Docker Buildx
92- uses : docker/setup-buildx-action@v3
162+ - uses : docker/setup-buildx-action@v3
93163
94- - name : Log in to GitHub Container Registry
95- uses : docker/login-action@v3
164+ - uses : docker/login-action@v3
96165 with :
97166 registry : ghcr.io
98167 username : ${{ github.actor }}
99168 password : ${{ secrets.GITHUB_TOKEN }}
100169
101- - name : Run GoReleaser
102- uses : goreleaser/goreleaser-action@v6
170+ - name : Docker meta
171+ id : meta
172+ uses : docker/metadata-action@v5
173+ with :
174+ images : ${{ env.REGISTRY_IMAGE }}
175+
176+ - name : Build and push by digest
177+ id : build
178+ uses : docker/build-push-action@v6
103179 with :
104- version : ' ~> v2'
105- args : release --clean
180+ context : .
181+ platforms : ${{ matrix.platform }}
182+ labels : ${{ steps.meta.outputs.labels }}
183+ outputs : type=image,name=${{ env.REGISTRY_IMAGE }},push-by-digest=true,name-canonical=true,push=true
184+
185+ - name : Export digest
186+ run : |
187+ mkdir -p "${{ runner.temp }}/digests"
188+ digest="${{ steps.build.outputs.digest }}"
189+ touch "${{ runner.temp }}/digests/${digest#sha256:}"
190+
191+ - uses : actions/upload-artifact@v4
192+ with :
193+ name : digests-${{ matrix.pair }}
194+ path : ${{ runner.temp }}/digests/*
195+ if-no-files-found : error
196+ retention-days : 1
197+
198+ merge-docker :
199+ name : Merge multi-arch manifest
200+ needs : [tag, build-docker]
201+ if : needs.tag.outputs.created == 'true'
202+ runs-on : ubuntu-latest
203+ steps :
204+ - name : Download digests
205+ uses : actions/download-artifact@v4
206+ with :
207+ path : ${{ runner.temp }}/digests
208+ pattern : digests-*
209+ merge-multiple : true
210+
211+ - uses : docker/setup-buildx-action@v3
212+
213+ - uses : docker/login-action@v3
214+ with :
215+ registry : ghcr.io
216+ username : ${{ github.actor }}
217+ password : ${{ secrets.GITHUB_TOKEN }}
218+
219+ - name : Docker meta
220+ id : meta
221+ uses : docker/metadata-action@v5
222+ with :
223+ images : ${{ env.REGISTRY_IMAGE }}
224+ tags : |
225+ type=raw,value=${{ needs.tag.outputs.tag }}
226+ type=raw,value=latest
227+ type=semver,pattern={{version}},value=${{ needs.tag.outputs.tag }}
228+ type=semver,pattern={{major}}.{{minor}},value=${{ needs.tag.outputs.tag }}
229+
230+ - name : Create manifest list and push
231+ working-directory : ${{ runner.temp }}/digests
232+ run : |
233+ # shellcheck disable=SC2046 # word-splitting is required to pass -t tags and digest refs as separate args
234+ docker buildx imagetools create \
235+ $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
236+ $(printf '${{ env.REGISTRY_IMAGE }}@sha256:%s ' *)
237+
238+ - name : Inspect image
239+ run : |
240+ docker buildx imagetools inspect "${{ env.REGISTRY_IMAGE }}:${{ needs.tag.outputs.tag }}"
241+
242+ release :
243+ name : Create GitHub release
244+ needs : [tag, build-binaries]
245+ if : needs.tag.outputs.created == 'true'
246+ runs-on : ubuntu-latest
247+ steps :
248+ - uses : actions/checkout@v4
249+ with :
250+ ref : ${{ needs.tag.outputs.tag }}
251+
252+ - name : Download binaries
253+ uses : actions/download-artifact@v4
254+ with :
255+ path : dist
256+ pattern : binary-*
257+ merge-multiple : true
258+
259+ - name : Generate checksums
260+ working-directory : dist
261+ run : |
262+ sha256sum gavel_* > checksums.txt
263+ cat checksums.txt
264+
265+ - name : Create release
106266 env :
107267 GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
108- GITHUB_OWNER : ${{ github.repository_owner }}
268+ TAG : ${{ needs.tag.outputs.tag }}
269+ run : |
270+ gh release create "$TAG" \
271+ --repo "${{ github.repository }}" \
272+ --title "Gavel $TAG" \
273+ --generate-notes \
274+ dist/gavel_*.tar.gz dist/gavel_*.zip dist/checksums.txt
0 commit comments