CI: sign Windows releases with Azure Artifact Signing (#62)
Build App / compute-version (push) Successful in 17s
Secret Scan / scan (push) Successful in 7s
Build App / build-macos (push) Successful in 3m6s
Build App / build-linux (push) Successful in 5m15s
Build App / build-windows (push) Successful in 5m52s
Build App / create-tag (push) Successful in 5s
Build App / sync-to-github (push) Successful in 1m50s
Build App / compute-version (push) Successful in 17s
Secret Scan / scan (push) Successful in 7s
Build App / build-macos (push) Successful in 3m6s
Build App / build-linux (push) Successful in 5m15s
Build App / build-windows (push) Successful in 5m52s
Build App / create-tag (push) Successful in 5s
Build App / sync-to-github (push) Successful in 1m50s
Windows releases are now signed with Azure Artifact Signing: the app binary, the MSI, the NSIS installer and its uninstaller, 5 signatures per release. Build-time WiX and NSIS DLLs are skipped. "Verify signatures" fails a release unless the installers, the binaries inside the MSI, and the logged app-binary and uninstaller signatures are all valid and timestamped. Previews are not signed and don't reference the signing secrets. The sign command reaches Tauri through `--config`; the v2 CLI never read TAURI_CONFIG, so the old inline override was a no-op. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit was merged in pull request #62.
This commit is contained in:
@@ -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.
|
||||
@@ -669,7 +671,10 @@ jobs:
|
||||
- name: Install Tauri CLI via cargo
|
||||
run: |
|
||||
set "PATH=%USERPROFILE%\.cargo\bin;C:\Program Files\nodejs;%PATH%"
|
||||
cargo install tauri-cli --version "^2"
|
||||
rem Pinned to the @tauri-apps/cli version in app/package-lock.json, which
|
||||
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
|
||||
run: |
|
||||
@@ -692,13 +697,21 @@ jobs:
|
||||
|
||||
- name: Build Tauri app
|
||||
working-directory: ./app
|
||||
# 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:
|
||||
TAURI_CONFIG: "{\"build\":{\"beforeBuildCommand\":\"\"}}"
|
||||
# See the matching comment on the Linux job's "Build Tauri app" step.
|
||||
TRIPLE_C_BUILD_SUFFIX: ${{ needs.compute-version.outputs.suffix }}
|
||||
run: |
|
||||
set "PATH=%USERPROFILE%\.cargo\bin;C:\Program Files\nodejs;%PATH%"
|
||||
cargo tauri build
|
||||
cargo tauri build --config "{\"build\":{\"beforeBuildCommand\":\"\"}}"
|
||||
|
||||
- name: Collect artifacts
|
||||
run: |
|
||||
|
||||
@@ -7,6 +7,7 @@ on:
|
||||
- "app/**"
|
||||
- "VERSION"
|
||||
- ".gitea/workflows/build-app.yml"
|
||||
- "scripts/windows-*.ps1"
|
||||
workflow_dispatch:
|
||||
|
||||
# Deliberately **not** on pull_request. Every publishing step here is gated on
|
||||
@@ -611,7 +612,11 @@ jobs:
|
||||
- name: Install Tauri CLI via cargo
|
||||
run: |
|
||||
set "PATH=%USERPROFILE%\.cargo\bin;C:\Program Files\nodejs;%PATH%"
|
||||
cargo install tauri-cli --version "^2"
|
||||
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.
|
||||
cargo install tauri-cli --version "=2.11.0" --locked
|
||||
|
||||
- name: Fix npm platform detection
|
||||
run: |
|
||||
@@ -632,10 +637,31 @@ jobs:
|
||||
set "PATH=%USERPROFILE%\.cargo\bin;C:\Program Files\nodejs;%PATH%"
|
||||
npm run build
|
||||
|
||||
# Releases are signed with Azure Artifact Signing (scripts/windows-*.ps1).
|
||||
# The setup fetches the signing client and a job-local .NET runtime, and
|
||||
# writes the Tauri config holding the sign command, which "Build Tauri
|
||||
# app" passes with --config. A missing secret fails here, before the build.
|
||||
- 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.
|
||||
env:
|
||||
TAURI_CONFIG: "{\"build\":{\"beforeBuildCommand\":\"\"}}"
|
||||
# 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%"
|
||||
rem Every Tauri bundler it downloads - candle.exe, light.exe and
|
||||
@@ -650,7 +676,20 @@ jobs:
|
||||
rem systemprofile\AppData\Local\tauri and systemprofile\.cache to the
|
||||
rem System32 originals, which makes the redirected view resolve. A
|
||||
rem runner running as a normal user needs no such patch.
|
||||
cargo tauri build --bundles msi,nsis
|
||||
cargo tauri build --bundles msi,nsis --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\bundle\msi\*.msi
|
||||
app\src-tauri\target\release\bundle\nsis\*.exe
|
||||
|
||||
# Tauri reports a failed sign command as just "failed to run powershell";
|
||||
# windows-sign.ps1 keeps its own transcript, signtool /debug included.
|
||||
- name: Show signing output
|
||||
if: failure()
|
||||
run: if exist .code-signing\sign-output.log type .code-signing\sign-output.log
|
||||
|
||||
- name: Collect artifacts
|
||||
run: |
|
||||
|
||||
Reference in New Issue
Block a user