Build App (Preview) / compute-version (pull_request) Successful in 5s
Secret Scan / scan (pull_request) Successful in 4s
Secret Scan / scan (push) Successful in 6s
Build App (Preview) / create-release (pull_request) Successful in 2s
Build App (Preview) / build-macos (pull_request) Successful in 3m19s
Build App (Preview) / test (pull_request) Successful in 4m59s
Build App (Preview) / build-linux (pull_request) Successful in 5m18s
Build App (Preview) / build-windows (pull_request) Failing after 5m32s
Build App (Preview) / prune-previews (pull_request) Skipped
Releases and PR previews now sign the app binary, the MSI, the NSIS installer and its uninstaller. "Verify signatures" fails the job on any unsigned or untimestamped .exe/.msi, so an unsigned installer can't ship quietly. - windows-signing-setup.ps1 fetches Microsoft.ArtifactSigning.Client 1.0.128 and a job-local .NET 10.0.12 runtime, each pinned by hash. Nothing is installed on the build VM. It also writes the dlib metadata and exports TAURI_CONFIG with bundle.windows.signCommand. - windows-sign.ps1 runs the installed signtool with /dlib, SHA-256 and the Microsoft timestamp server, with retries. Credentials come only from the AZURE_* environment. The metadata excludes every credential type except EnvironmentCredential, because InteractiveBrowserCredential would hang a job running as SYSTEM. - The signing files go in the workspace, not %TEMP%, because the uninstaller is signed from 32-bit makensis and WOW64 redirects SYSTEM's %TEMP%. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
55 lines
2.5 KiB
PowerShell
55 lines
2.5 KiB
PowerShell
# windows-sign.ps1 <file> - sign one file with Azure Artifact Signing.
|
|
#
|
|
# Tauri's bundle.windows.signCommand, set up by windows-signing-setup.ps1.
|
|
# Tauri calls it once per file it signs and fails the build on a non-zero exit.
|
|
#
|
|
# This may run as 32-bit PowerShell: the NSIS uninstaller is signed from inside
|
|
# makensis, which is 32-bit and resolves `powershell` to the SysWOW64 copy. So
|
|
# nothing here depends on $env:ProgramFiles or other per-bitness paths - every
|
|
# path comes in absolute from the setup script, and signtool is always the x64
|
|
# build, since that is what loads the x64 dlib.
|
|
#
|
|
# Credentials never touch a command line: the dlib reads AZURE_TENANT_ID,
|
|
# AZURE_CLIENT_ID and AZURE_CLIENT_SECRET from the environment itself.
|
|
|
|
param([Parameter(Mandatory = $true)][string]$Path)
|
|
|
|
$ErrorActionPreference = 'Stop'
|
|
|
|
foreach ($name in 'TRIPLE_C_SIGNTOOL', 'TRIPLE_C_SIGN_DLIB', 'TRIPLE_C_SIGN_METADATA', 'TRIPLE_C_SIGN_TIMESTAMP',
|
|
'AZURE_TENANT_ID', 'AZURE_CLIENT_ID', 'AZURE_CLIENT_SECRET') {
|
|
if (-not [Environment]::GetEnvironmentVariable($name)) {
|
|
throw "$name is not set - run windows-signing-setup.ps1 first and pass the AZURE_* secrets to this step"
|
|
}
|
|
}
|
|
if (-not (Test-Path -LiteralPath $Path)) { throw "No such file to sign: $Path" }
|
|
|
|
# /d names the product in the UAC prompt, which for an MSI would otherwise show
|
|
# a temporary file name. The timestamp is what keeps the signature valid after
|
|
# the short-lived Artifact Signing certificate expires, so it is not optional.
|
|
$arguments = @(
|
|
'sign', '/v',
|
|
'/fd', 'SHA256',
|
|
'/tr', $env:TRIPLE_C_SIGN_TIMESTAMP, '/td', 'SHA256',
|
|
'/d', 'Triple-C',
|
|
'/dlib', $env:TRIPLE_C_SIGN_DLIB,
|
|
'/dmdf', $env:TRIPLE_C_SIGN_METADATA,
|
|
$Path
|
|
)
|
|
|
|
# Timestamp servers and the signing endpoint both fail transiently now and
|
|
# then; a retry is cheaper than a failed three-platform release.
|
|
#
|
|
# Stop is relaxed around the call: Tauri captures this script's output, and
|
|
# PowerShell 5.1 turns a native command's stderr into error records when its
|
|
# own streams are redirected - under Stop, signtool's first warning would kill
|
|
# the script before its exit code is read.
|
|
$ErrorActionPreference = 'Continue'
|
|
for ($attempt = 1; $attempt -le 3; $attempt++) {
|
|
& $env:TRIPLE_C_SIGNTOOL @arguments 2>&1 | ForEach-Object { "$_" }
|
|
if ($LASTEXITCODE -eq 0) { exit 0 }
|
|
Write-Host "signtool exited $LASTEXITCODE signing $Path (attempt $attempt of 3)"
|
|
if ($attempt -lt 3) { Start-Sleep -Seconds (10 * $attempt) }
|
|
}
|
|
exit 1
|