44 push :
55 tags :
66 - " v*.*.*"
7+ - " !v*-nightly.*"
78 schedule :
8- - cron : " 0 9 * * *"
9+ - cron : " 0 */3 * * *"
910 workflow_dispatch :
1011 inputs :
1112 channel :
@@ -26,8 +27,45 @@ permissions:
2627 id-token : write
2728
2829jobs :
30+ check_changes :
31+ name : Check for changes since last nightly
32+ if : github.event_name == 'schedule'
33+ runs-on : ubuntu-24.04
34+ outputs :
35+ has_changes : ${{ steps.check.outputs.has_changes }}
36+ steps :
37+ - name : Checkout
38+ uses : actions/checkout@v6
39+ with :
40+ fetch-depth : 0
41+
42+ - id : check
43+ name : Compare HEAD to last nightly tag
44+ run : |
45+ last_nightly_tag=$(git tag --list 'v*-nightly.*' 'nightly-v*' --sort=-creatordate | head -n 1)
46+ if [[ -z "$last_nightly_tag" ]]; then
47+ echo "No previous nightly tag found. Proceeding with release."
48+ echo "has_changes=true" >> "$GITHUB_OUTPUT"
49+ exit 0
50+ fi
51+
52+ last_nightly_sha=$(git rev-parse "$last_nightly_tag^{commit}")
53+ head_sha=$(git rev-parse HEAD)
54+
55+ if [[ "$last_nightly_sha" == "$head_sha" ]]; then
56+ echo "No changes on main since last nightly release ($last_nightly_tag). Skipping."
57+ echo "has_changes=false" >> "$GITHUB_OUTPUT"
58+ else
59+ echo "Changes detected on main since $last_nightly_tag ($last_nightly_sha → $head_sha). Proceeding."
60+ echo "has_changes=true" >> "$GITHUB_OUTPUT"
61+ fi
62+
2963 preflight :
3064 name : Preflight
65+ needs : [check_changes]
66+ if : |
67+ !failure() && !cancelled() &&
68+ (github.event_name != 'schedule' || needs.check_changes.outputs.has_changes == 'true')
3169 runs-on : blacksmith-8vcpu-ubuntu-2404
3270 timeout-minutes : 10
3371 outputs :
@@ -134,6 +172,7 @@ jobs:
134172 build :
135173 name : Build ${{ matrix.label }}
136174 needs : preflight
175+ if : ${{ !failure() && !cancelled() && needs.preflight.result == 'success' }}
137176 runs-on : ${{ matrix.runner }}
138177 timeout-minutes : 30
139178 strategy :
@@ -156,7 +195,7 @@ jobs:
156195 target : AppImage
157196 arch : x64
158197 - label : Windows x64
159- runner : windows-2022 # blacksmith-32vcpu-windows-2025
198+ runner : blacksmith-32vcpu-windows-2025
160199 platform : win
161200 target : nsis
162201 arch : x64
@@ -188,6 +227,23 @@ jobs:
188227 - name : Align package versions to release version
189228 run : node scripts/update-release-package-versions.ts "${{ needs.preflight.outputs.version }}"
190229
230+ - name : Install Spectre-mitigated MSVC libs
231+ if : matrix.platform == 'win'
232+ shell : pwsh
233+ run : |
234+ $vswhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe"
235+ $installPath = & $vswhere -products * -latest -property installationPath
236+ $setupExe = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\setup.exe"
237+ $proc = Start-Process -FilePath $setupExe `
238+ -ArgumentList "modify", "--installPath", "`"$installPath`"", "--add", `
239+ "Microsoft.VisualStudio.Component.VC.Tools.x86.x64.Spectre", "--quiet", "--norestart" `
240+ -Wait -PassThru -NoNewWindow
241+ if ($null -eq $proc -or $proc.ExitCode -ne 0) {
242+ $code = if ($null -ne $proc) { $proc.ExitCode } else { 1 }
243+ Write-Error "Visual Studio Installer failed with exit code $code"
244+ exit $code
245+ }
246+
191247 - name : Build desktop artifact
192248 shell : bash
193249 env :
@@ -299,6 +355,7 @@ jobs:
299355 publish_cli :
300356 name : Publish CLI to npm
301357 needs : [preflight, build]
358+ if : ${{ !failure() && !cancelled() && needs.preflight.result == 'success' && needs.build.result == 'success' }}
302359 runs-on : ubuntu-24.04 # blacksmith-8vcpu-ubuntu-2404
303360 timeout-minutes : 10
304361 steps :
@@ -333,19 +390,36 @@ jobs:
333390 release :
334391 name : Publish GitHub Release
335392 needs : [preflight, build, publish_cli]
336- runs-on : blacksmith-8vcpu-ubuntu-2404
393+ if : ${{ !failure() && !cancelled() && needs.preflight.result == 'success' && needs.build.result == 'success' && needs.publish_cli.result == 'success' }}
394+ runs-on : ubuntu-24.04 # blacksmith-8vcpu-ubuntu-2404
337395 timeout-minutes : 10
338396 steps :
397+ - id : app_token
398+ name : Mint release app token
399+ uses : actions/create-github-app-token@v2
400+ with :
401+ app-id : ${{ secrets.RELEASE_APP_ID }}
402+ private-key : ${{ secrets.RELEASE_APP_PRIVATE_KEY }}
403+ owner : ${{ github.repository_owner }}
404+
339405 - name : Checkout
340406 uses : actions/checkout@v6
341407 with :
342408 ref : ${{ needs.preflight.outputs.ref }}
343409
410+ - name : Setup Bun
411+ uses : oven-sh/setup-bun@v2
412+ with :
413+ bun-version-file : package.json
414+
344415 - name : Setup Node
345416 uses : actions/setup-node@v6
346417 with :
347418 node-version-file : package.json
348419
420+ - name : Install dependencies
421+ run : bun install --frozen-lockfile
422+
349423 - name : Download all desktop artifacts
350424 uses : actions/download-artifact@v8
351425 with :
@@ -412,6 +486,7 @@ jobs:
412486 release-assets/*.blockmap
413487 release-assets/*.yml
414488 fail_on_unmatched_files : true
489+ token : ${{ steps.app_token.outputs.token }}
415490
416491 - name : Publish first release
417492 if : needs.preflight.outputs.previous_tag == ''
@@ -431,10 +506,11 @@ jobs:
431506 release-assets/*.blockmap
432507 release-assets/*.yml
433508 fail_on_unmatched_files : true
509+ token : ${{ steps.app_token.outputs.token }}
434510
435511 finalize :
436512 name : Finalize release
437- if : needs.preflight.outputs.release_channel == 'stable'
513+ if : ${{ !failure() && !cancelled() && needs.preflight.result == 'success' && needs.release.result == 'success' && needs.preflight. outputs.release_channel == 'stable' }}
438514 needs : [preflight, release]
439515 runs-on : blacksmith-8vcpu-ubuntu-2404
440516 timeout-minutes : 10
0 commit comments