ci: sign only what ships, stop signing previews, log signing output
Secret Scan / scan (push) Successful in 5s
Build App (Preview) / compute-version (pull_request) Successful in 4s
Secret Scan / scan (pull_request) Successful in 4s
Build App (Preview) / create-release (pull_request) Successful in 2s
Build App (Preview) / test (pull_request) Successful in 5m25s
Build App (Preview) / build-macos (pull_request) Successful in 4m15s
Build App (Preview) / build-windows (pull_request) Successful in 6m11s
Build App (Preview) / build-linux (pull_request) Successful in 14m11s
Build App (Preview) / prune-previews (pull_request) Successful in 5s

Artifact Signing is metered at about 1000 signatures a month, and there
were 67 Windows builds last month.

- windows-sign.ps1 signs only what reaches users: the app binary, the MSI,
  the NSIS installer and the uninstaller. It skips the WiX extension DLLs
  and NSIS plugins that Tauri also offers, and any file that is already
  validly signed. That is 4 signatures per release.
- Previews are no longer signed, so the preview workflow no longer
  references the signing secrets. A PR's workflow runs the PR's own code.
  The inline TAURI_CONFIG there, which the v2 CLI never read, becomes a
  real `--config`.
- Tauri reports a failed sign command only as "failed to run powershell".
  The script now keeps a transcript, signtool /debug included, and the
  release job prints it on failure.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-23 18:16:32 -07:00
co-authored by Claude Opus 5.5
parent cc274f39a8
commit a9432324a7
4 changed files with 100 additions and 73 deletions
+14 -36
View File
@@ -7,6 +7,8 @@ name: Build App (Preview)
# This is also the **PR build check**: it compiles Linux, macOS and Windows, so
# a push that breaks any of them fails here. Its `test` job runs vitest and
# `cargo test` too, so a push that breaks either suite fails here as well.
# Previews are not code-signed (releases are, in build-app.yml): see the
# comment on the Windows job's "Build Tauri app" step.
# build-app.yml used to do the build-check job in parallel and publish nothing,
# which meant six OS builds per push and one unreachable set of bundles; it is
# now releases-only.
@@ -75,7 +77,6 @@ on:
- "app/**"
- "VERSION"
- ".gitea/workflows/build-app-preview.yml"
- "scripts/windows-*.ps1"
workflow_dispatch:
jobs:
@@ -671,9 +672,8 @@ jobs:
run: |
set "PATH=%USERPROFILE%\.cargo\bin;C:\Program Files\nodejs;%PATH%"
rem Pinned to the @tauri-apps/cli version in app/package-lock.json, which
rem the Linux and macOS jobs run: the Windows code-signing path (sign
rem command, NSIS uninstaller signing) was verified against it, and "^2"
rem would change it underneath the pipeline on any Tauri release.
rem the Linux and macOS jobs run, and kept identical to build-app.yml so
rem a preview is built by the same bundler as the release it previews.
cargo install tauri-cli --version "=2.11.0" --locked
- name: Fix npm platform detection
@@ -695,45 +695,23 @@ jobs:
set "PATH=%USERPROFILE%\.cargo\bin;C:\Program Files\nodejs;%PATH%"
npm run build
# Previews are signed exactly like releases (build-app.yml): a preview is
# what gets installed for testing, and SmartScreen treats an unsigned one
# no differently from malware. The setup fetches the Artifact Signing
# client and a job-local .NET runtime, and writes the Tauri config holding
# the sign command, which "Build Tauri app" passes with --config.
- name: Prepare code signing
env:
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
ARTIFACT_SIGNING_ENDPOINT: ${{ secrets.ARTIFACT_SIGNING_ENDPOINT }}
ARTIFACT_SIGNING_ACCOUNT_NAME: ${{ secrets.ARTIFACT_SIGNING_ACCOUNT_NAME }}
ARTIFACT_SIGNING_PROFILE_NAME: ${{ secrets.ARTIFACT_SIGNING_PROFILE_NAME }}
run: powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File scripts\windows-signing-setup.ps1
- name: Build Tauri app
working-directory: ./app
# The sign command comes in through --config, from the file "Prepare
# code signing" wrote. Not TAURI_CONFIG: the v2 CLI never reads that
# variable (the inline one this step used to set was a no-op), and
# "Verify signatures" is what caught it.
# Previews are not code-signed: signing is metered, previews are built
# on every PR push, and a PR's workflow runs the PR's own code - so the
# signing secrets stay out of this workflow entirely. Releases are
# signed in build-app.yml.
#
# beforeBuildCommand is blanked through --config because the frontend
# was built in the step above. Not TAURI_CONFIG: the v2 CLI never
# reads that variable, and the inline one this step used to set was a
# no-op.
env:
# See the matching comment on the Linux job's "Build Tauri app" step.
TRIPLE_C_BUILD_SUFFIX: ${{ needs.compute-version.outputs.suffix }}
# Read by the signing dlib itself, never passed on a command line.
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
run: |
set "PATH=%USERPROFILE%\.cargo\bin;C:\Program Files\nodejs;%PATH%"
cargo tauri build --config "%TRIPLE_C_TAURI_SIGN_CONFIG%"
- name: Verify signatures
run: >-
powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass
-File scripts\windows-verify-signatures.ps1
app\src-tauri\target\release\triple-c.exe
app\src-tauri\target\release\bundle\msi\*.msi
app\src-tauri\target\release\bundle\nsis\*.exe
cargo tauri build --config "{\"build\":{\"beforeBuildCommand\":\"\"}}"
- name: Collect artifacts
run: |