Repository navigation
225 lines (204 loc) · 10.2 KB
/
Copy pathrelease.yml
File metadata and controls
225 lines (204 loc) · 10.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
name: Release
# Tag-driven: pushing a vX.Y.Z tag builds the cross matrix and publishes it.
# Nothing here runs on an ordinary push, so a release is always a deliberate
# act rather than a side effect of landing on main.
on:
push:
tags: ["v*"]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: false
# Read by default; only the publishing job widens to contents: write, and
# only far enough to create a release.
permissions:
contents: read
env:
# GitHub removes the Node 20 action runtime on 2026-09-16. mlugg/setup-zig still declares
# `using: node20` at its own latest release, so there is no version to upgrade to. This
# forces the post-cutover runtime now, on ordinary CI runs, rather than discovering on the
# 16th whether the action works under node24.
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
# npm 0.27.1 tarball (registry.npmjs.org/tree-sitter-cli/-/tree-sitter-cli-0.27.1.tgz).
TREE_SITTER_CLI_VERSION: "0.27.1"
TREE_SITTER_CLI_INTEGRITY: "sha512-WFPEjxwscCjZP9uYj0rxT2TyGBkDcXUkGTthrMpxZFGvzXEYsbC3J0633Ps8dd2mMsdsbU8oVwmQ148lLHI7Xw=="
# debian:bookworm-slim OCI index (linux/amd64 + linux/arm64), docker-library/repo-info
# repos/debian/remote/bookworm-slim.md (bookworm-20261005-slim).
DEBIAN_BOOKWORM_SLIM: debian@sha256:7c7b2c966bc9ee8cedfeef67e0e279108992c77681fa595db4a9d65c06ccc587
jobs:
# No darwin job: fleet workflows run no macOS runners, and zig cannot
# link darwin without a macOS SDK (docs/INSTALL.md § Cross builds), so
# releases ship only what this Linux job can cross-compile.
#
# Build never holds id-token: npm install of tree-sitter-cli (postinstall)
# and docker run must not sit next to OIDC that can mint a Sigstore identity.
# Sign is a later job with id-token only, after artifacts are already in
# Actions storage. Publish is later still so contents: write is not in
# scope while npm, zig, wine, docker, or cosign run.
build:
name: build
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
contents: read
steps:
# fetch-depth: 0 because the Makefile stamps the binary from
# `git describe --tags`, which reports a bare vX.Y.Z only when the tag
# and its history are both present. A shallow checkout would ship
# binaries versioned as a bare SHA.
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
persist-credentials: false
- uses: Rethunk-Tech/gh-actions/setup-go@67ec8bd68343d915462729ad119c355740cf6205 # v1.22
# zig is the single cross-compilation toolchain `make cross` drives;
# rgit links tree-sitter through cgo, so CGO_ENABLED=0 is not an
# option and every target needs a real C compiler
# (docs/INSTALL.md § Cross builds).
- uses: mlugg/setup-zig@d1434d08867e3ee9daa34448df10607b98908d29 # v2.2.1
# The tree-sitter CLI is what lets the release carry SQL support: the
# grammar module ships no usable parser.c, so `make cross` generates
# one via cmd/rgit-install. Without this step every artifact would
# still build, just SQL-less (docs/INSTALL.md § SQL support).
# Version + npm integrity of the tarball, then install from the local
# file so a registry swap cannot change what postinstall runs.
- name: Install pinned tree-sitter CLI
run: |
tgz="$RUNNER_TEMP/tree-sitter-cli-${TREE_SITTER_CLI_VERSION}.tgz"
curl -fsSL -o "$tgz" \
"https://registry.npmjs.org/tree-sitter-cli/-/tree-sitter-cli-${TREE_SITTER_CLI_VERSION}.tgz"
got="sha512-$(openssl dgst -sha512 -binary "$tgz" | openssl base64 -A)"
test "$got" = "$TREE_SITTER_CLI_INTEGRITY"
npm install -g "$tgz"
- run: make cross
# Completions and the man page are arch-independent text generated
# from this CLI (make completions-man). Fail here rather than
# publishing binaries without the tarball SHA256SUMS promises.
- name: verify completions and man page tarball
run: |
tar -tzf dist/rgit-completions-man.tar.gz | grep -qx rgit.bash
tar -tzf dist/rgit-completions-man.tar.gz | grep -qx _rgit
tar -tzf dist/rgit-completions-man.tar.gz | grep -qx rgit.fish
tar -tzf dist/rgit-completions-man.tar.gz | grep -qx rgit.ps1
tar -tzf dist/rgit-completions-man.tar.gz | grep -qx rgit.1
grep -q ' rgit-completions-man.tar.gz$' dist/SHA256SUMS
# Fail loudly rather than publishing a release whose binaries quietly
# lack the grammar this workflow installed a toolchain for.
- name: verify the linux/amd64 artifact carries SQL
run: |
bin=$(find dist -name '*-linux-amd64' -type f)
chmod +x "$bin"
"$bin" --version
"$bin" languages | grep -q '^sql' || {
echo "::error::release artifact has no sql grammar"; exit 1;
}
# linux/amd64 above is the runner's own native arch, execed directly.
# linux/arm64 cannot be: it is dynamically linked against glibc
# (rgit links tree-sitter through cgo, so this is not a static Go
# binary), and bare QEMU user-mode emulation has no aarch64 sysroot
# to resolve /lib/ld-linux-aarch64.so.1 against on an amd64 host --
# confirmed directly (`qemu-aarch64 ./rgit-...-linux-arm64` fails
# with exactly that "could not open" error). Registering QEMU's
# binfmt_misc handlers and running the binary *inside* a real
# arm64 container image is what actually works: the image supplies
# the matching glibc, and QEMU (via binfmt) transparently emulates
# the container's own arm64 process for it -- the same mechanism
# `docker buildx` uses for multi-arch image builds, just running a
# bare binary instead of a build. Verified directly against this
# exact artifact before writing this step, not assumed from how
# QEMU emulation is commonly described.
- uses: docker/setup-qemu-action@99012661954931238ded8c8b007157a8430204e1 # v4.4.0
with:
platforms: arm64
# Copy the one binary into a throwaway dir and mount it read-only so
# a compromised image cannot rewrite dist/ (or SHA256SUMS) before
# the later sign job Cosign-signs the checksums.
- name: verify the linux/arm64 artifact carries SQL
run: |
bin=$(find dist -name '*-linux-arm64' -type f)
work=$(mktemp -d)
trap 'rm -rf "$work"' EXIT
cp "$bin" "$work/rgit"
chmod +x "$work/rgit"
docker run --rm --platform=linux/arm64 -v "$work:/artifact:ro" "$DEBIAN_BOOKWORM_SLIM" \
/artifact/rgit --version
docker run --rm --platform=linux/arm64 -v "$work:/artifact:ro" "$DEBIAN_BOOKWORM_SLIM" \
/artifact/rgit languages | grep -q '^sql' || {
echo "::error::release artifact has no sql grammar"; exit 1;
}
# Wine runs the windows/amd64 PE binary directly on the linux runner.
# Not preinstalled on ubuntu-latest (actions/runner-images' own
# software manifest), unlike shellcheck/sha256sum above -- installed
# here rather than via a marketplace action, since it is a single
# well-known apt package and this workflow already prefers plain
# `run:` steps over an action wherever apt covers it in one line.
# The apt package is "wine64" but the binary it installs is plain
# "wine" -- confirmed directly (`dpkg -L wine64` lists /usr/bin/wine,
# no wine64 binary at all on Ubuntu 24.04), a real trap the package
# name alone does not warn you about.
- name: install wine
run: |
sudo apt-get update
sudo apt-get install -y wine64
# First run is noisy on stderr -- wine lazily creates ~/.wine and
# spawns its own explorer/services helper processes, which complain
# about a missing display and missing 32-bit support (wine32,
# irrelevant to a console-only 64-bit exe like this one). That noise
# never reaches stdout, so it does not affect the grep below;
# confirmed directly rather than assumed, since a wall of "err:"
# lines looks alarming enough to mistake for a real failure.
- name: verify the windows/amd64 artifact carries SQL
run: |
bin=$(find dist -name '*-windows-amd64.exe' -type f)
wine "$bin" --version
wine "$bin" languages | grep -q '^sql' || {
echo "::error::release artifact has no sql grammar"; exit 1;
}
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: dist
path: dist/
sign:
name: sign checksums
needs: build
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
id-token: write # keyless cosign signing (Sigstore OIDC)
contents: read
steps:
- uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
name: dist
path: dist
- uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2
# Keyless: signs with a short-lived OIDC-issued cert instead of a
# managed private key, so there is no signing key to rotate or leak.
# Signs SHA256SUMS, not each binary -- the checksums already commit to
# every artifact's contents, one signature covers the whole release.
- name: sign checksums
run: cosign sign-blob --yes --bundle dist/SHA256SUMS.sigstore.json dist/SHA256SUMS
# Distinct artifact name: upload-artifact names must be unique in a run.
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: dist-signed
path: dist/
publish:
name: publish
needs: sign
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: write
steps:
- uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
name: dist-signed
path: dist
- name: publish
env:
GH_TOKEN: ${{ github.token }}
GH_REPO: ${{ github.repository }}
run: |
gh release create "$GITHUB_REF_NAME" dist/* \
--title "$GITHUB_REF_NAME" \
--generate-notes