@@ -88,10 +88,13 @@ jobs:
8888 retention-days : 7
8989
9090 build :
91- name : Build signed ${{ matrix.name }} installer
91+ name : Build ${{ matrix.name }} installer
9292 needs : validate
9393 runs-on : ${{ matrix.os }}
9494 timeout-minutes : 60
95+ env :
96+ WINDOWS_SIGNING_AVAILABLE : ${{ secrets.WINDOWS_CERTIFICATE != '' && secrets.WINDOWS_CERTIFICATE_PASSWORD != '' }}
97+ APPLE_SIGNING_AVAILABLE : ${{ secrets.APPLE_CERTIFICATE != '' && secrets.APPLE_CERTIFICATE_PASSWORD != '' && secrets.APPLE_SIGNING_IDENTITY != '' && secrets.APPLE_ID != '' && secrets.APPLE_PASSWORD != '' && secrets.APPLE_TEAM_ID != '' }}
9598 strategy :
9699 fail-fast : false
97100 matrix :
@@ -126,7 +129,8 @@ jobs:
126129 patchelf \
127130 libudev-dev \
128131 dbus-x11 \
129- xvfb
132+ xvfb \
133+ webkit2gtk-driver
130134
131135 - name : Setup pnpm
132136 uses : pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5
@@ -147,7 +151,7 @@ jobs:
147151 run : pnpm install --frozen-lockfile
148152
149153 - name : Import Windows signing certificate
150- if : runner.os == 'Windows'
154+ if : runner.os == 'Windows' && env.WINDOWS_SIGNING_AVAILABLE == 'true'
151155 shell : pwsh
152156 env :
153157 WINDOWS_CERTIFICATE : ${{ secrets.WINDOWS_CERTIFICATE }}
@@ -165,7 +169,7 @@ jobs:
165169 "WINDOWS_CERTIFICATE_THUMBPRINT=$($cert.Thumbprint)" >> $env:GITHUB_ENV
166170
167171 - name : Verify Apple signing and notarization secrets
168- if : runner.os == 'macOS'
172+ if : runner.os == 'macOS' && env.APPLE_SIGNING_AVAILABLE == 'true'
169173 shell : bash
170174 env :
171175 APPLE_CERTIFICATE : ${{ secrets.APPLE_CERTIFICATE }}
@@ -180,23 +184,34 @@ jobs:
180184 test -n "${!name}" || { echo "$name is required" >&2; exit 1; }
181185 done
182186
183- - name : Build signed Windows NSIS installer
187+ - name : Report unsigned platform fallback
188+ if : >-
189+ (runner.os == 'Windows' && env.WINDOWS_SIGNING_AVAILABLE != 'true') ||
190+ (runner.os == 'macOS' && env.APPLE_SIGNING_AVAILABLE != 'true')
191+ shell : bash
192+ run : echo "::warning::Platform signing secrets are not configured; this installer will be explicitly marked unsigned."
193+
194+ - name : Build Windows NSIS installer
184195 if : runner.os == 'Windows'
185196 shell : pwsh
186197 run : |
187- $config = @{
188- bundle = @{
189- windows = @{
190- certificateThumbprint = $env:WINDOWS_CERTIFICATE_THUMBPRINT
191- digestAlgorithm = 'sha256'
192- timestampUrl = 'http://timestamp.digicert.com'
198+ if ($env:WINDOWS_SIGNING_AVAILABLE -eq 'true') {
199+ $config = @{
200+ bundle = @{
201+ windows = @{
202+ certificateThumbprint = $env:WINDOWS_CERTIFICATE_THUMBPRINT
203+ digestAlgorithm = 'sha256'
204+ timestampUrl = 'http://timestamp.digicert.com'
205+ }
193206 }
194- }
195- } | ConvertTo-Json -Compress -Depth 5
196- pnpm tauri:build --target ${{ matrix.target }} --bundles nsis --config $config
207+ } | ConvertTo-Json -Compress -Depth 5
208+ pnpm tauri:build --target ${{ matrix.target }} --bundles nsis --config $config
209+ } else {
210+ pnpm tauri:build --target ${{ matrix.target }} --bundles nsis
211+ }
197212
198213 - name : Build signed and notarized macOS DMG
199- if : runner.os == 'macOS'
214+ if : runner.os == 'macOS' && env.APPLE_SIGNING_AVAILABLE == 'true'
200215 env :
201216 APPLE_CERTIFICATE : ${{ secrets.APPLE_CERTIFICATE }}
202217 APPLE_CERTIFICATE_PASSWORD : ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
@@ -206,6 +221,10 @@ jobs:
206221 APPLE_TEAM_ID : ${{ secrets.APPLE_TEAM_ID }}
207222 run : pnpm tauri:build --target ${{ matrix.target }} --bundles dmg
208223
224+ - name : Build unsigned macOS DMG
225+ if : runner.os == 'macOS' && env.APPLE_SIGNING_AVAILABLE != 'true'
226+ run : pnpm tauri:build --target ${{ matrix.target }} --bundles dmg
227+
209228 - name : Build Linux AppImage and deb installers
210229 if : runner.os == 'Linux'
211230 run : pnpm tauri:build --target ${{ matrix.target }} --bundles appimage,deb
@@ -229,8 +248,15 @@ jobs:
229248 New-Item -ItemType Directory -Force release-assets | Out-Null
230249 $installers = Get-ChildItem 'target/${{ matrix.target }}/release/bundle/nsis/*.exe'
231250 if ($installers.Count -ne 1) { throw "expected one NSIS installer, found $($installers.Count)" }
232- $signature = Get-AuthenticodeSignature $installers[0].FullName
233- if ($signature.Status -ne 'Valid') { throw "invalid Authenticode signature: $($signature.Status)" }
251+ if ($env:WINDOWS_SIGNING_AVAILABLE -eq 'true') {
252+ $signature = Get-AuthenticodeSignature $installers[0].FullName
253+ if ($signature.Status -ne 'Valid') { throw "invalid Authenticode signature: $($signature.Status)" }
254+ '- Windows NSIS: Authenticode signed and verified.' |
255+ Set-Content release-assets/windows-signing-status.txt
256+ } else {
257+ '- Windows NSIS: unsigned (signing secrets were not configured).' |
258+ Set-Content release-assets/windows-signing-status.txt
259+ }
234260
235261 $installRoot = Join-Path $env:RUNNER_TEMP 'bbcom-smoke'
236262 Start-Process -FilePath $installers[0].FullName -ArgumentList '/S', "/D=$installRoot" -Wait
@@ -261,8 +287,16 @@ jobs:
261287 dmg=(target/${{ matrix.target }}/release/bundle/dmg/*.dmg)
262288 test "${#app[@]}" -eq 1
263289 test "${#dmg[@]}" -eq 1
264- codesign --verify --deep --strict --verbose=2 "${app[0]}"
265- xcrun stapler validate "${dmg[0]}"
290+ mkdir -p release-assets
291+ if [[ "$APPLE_SIGNING_AVAILABLE" == 'true' ]]; then
292+ codesign --verify --deep --strict --verbose=2 "${app[0]}"
293+ xcrun stapler validate "${dmg[0]}"
294+ echo '- macOS DMG: Developer ID signed and notarized.' \
295+ > release-assets/macos-signing-status.txt
296+ else
297+ echo '- macOS DMG: unsigned and not notarized (signing secrets were not configured).' \
298+ > release-assets/macos-signing-status.txt
299+ fi
266300
267301 mount_dir="$RUNNER_TEMP/bbcom-dmg"
268302 install_dir="$RUNNER_TEMP/bbcom-smoke-applications"
@@ -309,7 +343,6 @@ jobs:
309343 test ! -e "$installed_app"
310344 hdiutil detach "$mount_dir"
311345 rm -rf "$mount_dir"
312- mkdir -p release-assets
313346 cp "${dmg[0]}" release-assets/
314347
315348 - name : Verify, launch, and uninstall Linux installers
@@ -350,6 +383,8 @@ jobs:
350383 test "$(dpkg-query -W -f='${db:Status-Status}' "$package" 2>/dev/null || true)" != installed
351384 mkdir -p release-assets
352385 cp "${appimage[0]}" "${deb[0]}" release-assets/
386+ echo '- Linux AppImage/deb: Sigstore keyless bundles are attached by the release job.' \
387+ > release-assets/linux-signing-status.txt
353388
354389 - name : Upload installer
355390 uses : actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
@@ -387,11 +422,13 @@ jobs:
387422 appimage=(release/*.AppImage)
388423 deb=(release/*.deb)
389424 sbom=(release/*.cdx.json)
425+ signing_status=(release/*-signing-status.txt)
390426 test "${#nsis[@]}" -eq 1
391427 test "${#dmg[@]}" -eq 1
392428 test "${#appimage[@]}" -eq 1
393429 test "${#deb[@]}" -eq 1
394430 test "${#sbom[@]}" -eq 1
431+ test "${#signing_status[@]}" -eq 3
395432 test -f release/frontend-licenses.json
396433 test -f release/rust-licenses.json
397434
@@ -410,17 +447,24 @@ jobs:
410447 run : |
411448 (
412449 cd release
450+ checksum_tmp="../SHA256SUMS.tmp"
413451 find . -maxdepth 1 -type f ! -name SHA256SUMS -print0 \
414452 | sort -z \
415453 | xargs -0 sha256sum \
416- | sed 's# \./# #' > SHA256SUMS
454+ | sed 's# \./# #' > "$checksum_tmp"
455+ mv "$checksum_tmp" SHA256SUMS
417456 )
418457 version="${GITHUB_REF_NAME#v}"
419458 awk -v heading="## [$version]" '
420459 index($0, heading) == 1 { found=1; next }
421460 found && /^## \[/ { exit }
422461 found { print }
423462 ' CHANGELOG.md > release-notes.md
463+ {
464+ echo
465+ echo '## Artifact signing status'
466+ cat release/*-signing-status.txt
467+ } >> release-notes.md
424468 test -s release-notes.md
425469
426470 - name : Attest release artifacts
0 commit comments