11name : Release
22
3+ run-name : ${{ format('Release {0} [{1}]', github.event.inputs.release_tag, github.event.inputs.dry_run == 'true' && 'dry-run' || 'live') }}
4+
35on :
46 workflow_dispatch :
7+ inputs :
8+ release_tag :
9+ description : " Release tag (e.g. v1.9.0)"
10+ required : true
11+ dry_run :
12+ description : " Run in dry-run mode"
13+ required : true
14+ type : boolean
15+ default : true
16+ release_crates :
17+ description : " Release crates.io packages"
18+ required : true
19+ type : boolean
20+ default : false
21+ release_csharp :
22+ description : " Release C# SDK"
23+ required : true
24+ type : boolean
25+ default : false
26+ release_cpp :
27+ description : " Release C++ bindings"
28+ required : true
29+ type : boolean
30+ default : false
31+ release_npm :
32+ description : " Release NPM package"
33+ required : true
34+ type : boolean
35+ default : false
36+ release_docker :
37+ description : " Release Docker container"
38+ required : true
39+ type : boolean
40+ default : false
41+ update_mirror_latest_version :
42+ description : " Update S3 mirror latest-version marker"
43+ required : true
44+ type : boolean
45+ default : false
546
647permissions :
748 contents : write
@@ -12,8 +53,337 @@ concurrency:
1253 cancel-in-progress : true
1354
1455jobs :
15- foo :
56+ # This job runs before all of our release jobs. If there is a release problem we should
57+ # try to fail during this step to prevent partial releases.
58+ build-cargo-release :
59+ runs-on : spacetimedb-new-runner-2
60+ steps :
61+ - name : Checkout
62+ uses : actions/checkout@v4
63+ with :
64+ submodules : recursive
65+
66+ - name : Set up Rust
67+ uses : dsherret/rust-toolchain-file@v1
68+ - name : Set default rust toolchain
69+ run : rustup default $(rustup show active-toolchain | cut -d' ' -f1)
70+
71+ - name : Cache cargo
72+ uses : swatinem/rust-cache@v2
73+ with :
74+ workspaces : ./
75+
76+ - name : Install cargo-release
77+ run : |
78+ cargo install --path tools/release
79+ # ensure the binary exists
80+ which cargo-release
81+ # copy it into a sharable directory
82+ mkdir -p shared-bin
83+ cp "$(which cargo-release)" shared-bin/
84+
85+ - name : Upload build artifacts
86+ uses : actions/upload-artifact@v4
87+ with :
88+ name : cargo-release-bin
89+ path : shared-bin/
90+
91+ release-crates :
92+ needs : build-cargo-release
93+ runs-on : spacetimedb-new-runner-2
94+ if : ${{ inputs.release_crates }}
95+ env :
96+ CARGO_TERM_COLOR : always
97+ CARGO_REGISTRY_TOKEN : ${{ secrets.CARGO_REGISTRY_TOKEN }}
98+ GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
99+
100+ steps :
101+ - name : Checkout specific tag
102+ uses : actions/checkout@v4
103+ with :
104+ ref : ${{ github.event.inputs.release_tag }}
105+ submodules : recursive
106+
107+ - name : Set up Rust
108+ uses : dsherret/rust-toolchain-file@v1
109+ - name : Set default rust toolchain
110+ run : rustup default $(rustup show active-toolchain | cut -d' ' -f1)
111+
112+ - name : Download cargo-release
113+ uses : actions/download-artifact@v4
114+ with :
115+ name : cargo-release-bin
116+ path : ./shared-bin
117+
118+ - name : Make binary executable and on PATH
119+ run : |
120+ chmod +x ./shared-bin/cargo-release
121+ echo "$PWD/shared-bin" >> "$GITHUB_PATH"
122+
123+ # TODO: dry-run via publishing to a local registry: https://doc.rust-lang.org/cargo/reference/registries.html
124+ - name : Run release (dry-run)
125+ if : ${{ inputs.dry_run }}
126+ # NOTE: This will print a warning that `cargo-release release crates` dry runs are not supported
127+ run : cargo-release release crates --dry-run
128+
129+ - name : Run release
130+ if : ${{ !inputs.dry_run }}
131+ run : cargo-release release crates
132+
133+ release-csharp :
134+ needs : build-cargo-release
135+ runs-on : spacetimedb-new-runner-2
136+ if : ${{ inputs.release_csharp }}
137+ env :
138+ CARGO_TERM_COLOR : always
139+ GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
140+ NUGET_API_KEY : ${{ secrets.NUGET_API_KEY }}
141+
142+ steps :
143+ - name : Checkout specific tag
144+ uses : actions/checkout@v4
145+ with :
146+ ref : ${{ github.event.inputs.release_tag }}
147+ submodules : recursive
148+
149+ - name : Set up Rust
150+ uses : dsherret/rust-toolchain-file@v1
151+ - name : Set default rust toolchain
152+ run : rustup default $(rustup show active-toolchain | cut -d' ' -f1)
153+
154+ - name : Download cargo-release
155+ uses : actions/download-artifact@v4
156+ with :
157+ name : cargo-release-bin
158+ path : ./shared-bin
159+
160+ - name : Make binary executable and on PATH
161+ run : |
162+ chmod +x ./shared-bin/cargo-release
163+ echo "$PWD/shared-bin" >> "$GITHUB_PATH"
164+
165+ - name : Set up .NET
166+ uses : actions/setup-dotnet@v4
167+ with :
168+ global-json-path : global.json
169+
170+ - name : Install NuGet
171+ shell : bash
172+ run : |
173+ sudo apt install -y mono-complete
174+ mkdir bin
175+ cd bin
176+ wget https://dist.nuget.org/win-x86-commandline/latest/nuget.exe
177+ # We're on linux, so we need to do a mono dance to make NuGet invocations look the same as they would on e.g. windows
178+ mv nuget.exe nuget-mono.exe
179+ cat <<'EOF' | sed 's/^ *//' >nuget
180+ #!/bin/bash
181+ DIR="$(dirname "$(readlink -f "$0")")"
182+ mono "$DIR/nuget-mono.exe" "$@"
183+ EOF
184+ chmod +x nuget
185+ echo "$PWD" >> $GITHUB_PATH
186+
187+ - name : Setup SSH key for Unity SDK repo
188+ uses : webfactory/ssh-agent@v0.9.0
189+ with :
190+ ssh-private-key : ${{ secrets.UNITY_SDK_DEPLOY_KEY }}
191+
192+ - name : Configure git
193+ run : |
194+ git config --global user.name "Release Bot"
195+ git config --global user.email "no-reply@clockworklabs.io"
196+ # Remove any HTTPS to SSH conversion set by checkout action
197+ git config --global --unset-all url.https://github.com/.insteadOf || true
198+ # Ensure SSH is used instead of HTTPS for GitHub
199+ git config --global url."git@github.com:".insteadOf "https://github.com/"
200+ # Verify configuration
201+ echo "Git URL rewrite config:"
202+ git config --global --get-regexp url
203+
204+ - name : Run C# SDK release (dry-run)
205+ if : ${{ inputs.dry_run }}
206+ run : cargo-release release csharp ${{ github.event.inputs.release_tag }} --dry-run
207+
208+ - name : Run C# SDK release
209+ if : ${{ !inputs.dry_run }}
210+ run : cargo-release release csharp ${{ github.event.inputs.release_tag }}
211+
212+ release-cpp :
213+ needs : build-cargo-release
214+ runs-on : spacetimedb-new-runner-2
215+ if : ${{ inputs.release_cpp }}
216+ env :
217+ CARGO_TERM_COLOR : always
218+ GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
219+
220+ steps :
221+ - name : Checkout specific tag
222+ uses : actions/checkout@v4
223+ with :
224+ ref : ${{ github.event.inputs.release_tag }}
225+ submodules : recursive
226+
227+ - name : Set up Rust
228+ uses : dsherret/rust-toolchain-file@v1
229+ - name : Set default rust toolchain
230+ run : rustup default $(rustup show active-toolchain | cut -d' ' -f1)
231+
232+ - name : Download cargo-release
233+ uses : actions/download-artifact@v4
234+ with :
235+ name : cargo-release-bin
236+ path : ./shared-bin
237+
238+ - name : Make binary executable and on PATH
239+ run : |
240+ chmod +x ./shared-bin/cargo-release
241+ echo "$PWD/shared-bin" >> "$GITHUB_PATH"
242+
243+ - name : Setup SSH key for C++ SDK repo
244+ uses : webfactory/ssh-agent@v0.9.0
245+ with :
246+ ssh-private-key : ${{ secrets.CPP_SDK_DEPLOY_KEY }}
247+
248+ - name : Configure git
249+ run : |
250+ git config --global user.name "Release Bot"
251+ git config --global user.email "no-reply@clockworklabs.io"
252+ # Remove any HTTPS to SSH conversion set by checkout action
253+ git config --global --unset-all url.https://github.com/.insteadOf || true
254+ # Ensure SSH is used instead of HTTPS for GitHub
255+ git config --global url."git@github.com:".insteadOf "https://github.com/"
256+ # Verify configuration
257+ echo "Git URL rewrite config:"
258+ git config --global --get-regexp url
259+
260+ - name : Run C++ SDK release (dry-run)
261+ if : ${{ inputs.dry_run }}
262+ run : cargo-release release cpp ${{ github.event.inputs.release_tag }} --dry-run
263+
264+ - name : Run C++ SDK release
265+ if : ${{ !inputs.dry_run }}
266+ run : cargo-release release cpp ${{ github.event.inputs.release_tag }}
267+
268+ release-npm :
269+ needs : build-cargo-release
16270 runs-on : ubuntu-latest
271+ if : ${{ inputs.release_npm }}
272+ env :
273+ CARGO_TERM_COLOR : always
274+ GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
275+
276+ permissions :
277+ id-token : write
278+ contents : write
279+ packages : write
280+
17281 steps :
18- - name : Be done
19- run : echo
282+ - name : Checkout specific tag
283+ uses : actions/checkout@v4
284+ with :
285+ ref : ${{ github.event.inputs.release_tag }}
286+ submodules : recursive
287+
288+ - name : Download cargo-release
289+ uses : actions/download-artifact@v4
290+ with :
291+ name : cargo-release-bin
292+ path : ./shared-bin
293+
294+ - name : Make binary executable and on PATH
295+ run : |
296+ chmod +x ./shared-bin/cargo-release
297+ echo "$PWD/shared-bin" >> "$GITHUB_PATH"
298+
299+ - name : Set up Node.js
300+ uses : actions/setup-node@v4
301+ with :
302+ node-version : ' 22.x'
303+ registry-url : ' https://registry.npmjs.org'
304+
305+ - name : Install pnpm
306+ run : npm install -g pnpm
307+
308+ - name : Run NPM release (dry-run)
309+ if : ${{ inputs.dry_run }}
310+ run : cargo-release release npm ${{ github.event.inputs.release_tag }} --dry-run
311+
312+ - name : Run NPM release
313+ if : ${{ !inputs.dry_run }}
314+ run : cargo-release release npm ${{ github.event.inputs.release_tag }}
315+
316+ release-docker :
317+ needs : build-cargo-release
318+ runs-on : spacetimedb-new-runner-2
319+ env :
320+ CARGO_TERM_COLOR : always
321+ GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
322+ if : ${{ inputs.release_docker }}
323+
324+ steps :
325+ - name : Checkout specific tag
326+ uses : actions/checkout@v4
327+ with :
328+ ref : ${{ github.event.inputs.release_tag }}
329+ submodules : recursive
330+
331+ - name : Download cargo-release
332+ uses : actions/download-artifact@v4
333+ with :
334+ name : cargo-release-bin
335+ path : ./shared-bin
336+
337+ - name : Make binary executable and on PATH
338+ run : |
339+ chmod +x ./shared-bin/cargo-release
340+ echo "$PWD/shared-bin" >> "$GITHUB_PATH"
341+
342+ # We need network=host during dry-runs but it's fine during non dry-runs as well
343+ - name : Set up Docker Buildx
344+ uses : docker/setup-buildx-action@v3
345+ with :
346+ driver-opts : network=host
347+ - name : Login to DockerHub
348+ uses : docker/login-action@v3
349+ if : ${{ !inputs.dry_run }}
350+ with :
351+ username : ${{ vars.DOCKERHUB_USERNAME }}
352+ # Docker Hub access tokens are passed to docker/login-action via the password input.
353+ password : ${{ secrets.DOCKERHUB_TOKEN }}
354+ - name : Run Docker release
355+ run : cargo-release release docker ${{ github.event.inputs.release_tag }} ${{ inputs.dry_run && '--dry-run' || '' }}
356+
357+ update-mirror-latest-version :
358+ runs-on : ubuntu-latest
359+ if : ${{ !inputs.dry_run && inputs.update_mirror_latest_version }}
360+
361+ steps :
362+ - name : Verify mirror tag prefix exists
363+ env :
364+ RELEASE_TAG : ${{ github.event.inputs.release_tag }}
365+ AWS_ACCESS_KEY_ID : ${{ secrets.AWS_KEY_ID }}
366+ AWS_SECRET_ACCESS_KEY : ${{ secrets.AWS_SECRET_ACCESS_KEY }}
367+ AWS_DEFAULT_REGION : us-east-1
368+ run : |
369+ set -uo pipefail
370+
371+ PREFIX="refs/tags/$RELEASE_TAG/"
372+ COUNT="$(aws s3api list-objects-v2 \
373+ --bucket spacetimedb-client-binaries \
374+ --prefix "$PREFIX" \
375+ --max-keys 1 \
376+ --query 'length(not_null(Contents, `[]`))')"
377+ test "$COUNT" -gt 0
378+
379+ - name : Generate latest-version marker
380+ env :
381+ RELEASE_TAG : ${{ github.event.inputs.release_tag }}
382+ run : printf '%s\n' "$RELEASE_TAG" > latest-version
383+
384+ - name : Upload latest-version to S3 mirror
385+ env :
386+ AWS_ACCESS_KEY_ID : ${{ secrets.AWS_KEY_ID }}
387+ AWS_SECRET_ACCESS_KEY : ${{ secrets.AWS_SECRET_ACCESS_KEY }}
388+ AWS_DEFAULT_REGION : us-east-1
389+ run : aws s3 cp latest-version s3://spacetimedb-client-binaries/latest-version --acl public-read
0 commit comments