From 3121122cc1e64203dae3afb7bc0568142670f5ba Mon Sep 17 00:00:00 2001 From: Michael Suchacz <203725896+ibetitsmike@users.noreply.github.com> Date: Thu, 5 Mar 2026 03:28:39 +0000 Subject: [PATCH 1/2] fix: resolve absolute paths in Windows signCommand for Tauri bundler --- .github/workflows/release.yml | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6f5c916..d063b1c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -86,21 +86,26 @@ jobs: - name: Configure Tauri Windows signCommand if: matrix.platform == 'windows-latest' && env.JSIGN_PATH != '' - shell: bash + shell: pwsh run: | - cat > signing.conf.json << 'EOF' - { - "bundle": { - "windows": { - "signCommand": { - "cmd": "pwsh", - "args": ["-File", "scripts/sign-windows.ps1", "%1"] - } + # Resolve absolute paths — Tauri's bundler uses std::process::Command + # (no shell) so bare names like 'pwsh' fail PATH lookup on Windows. + $pwshPath = (Get-Command pwsh).Source -replace '\\', '/' + $scriptPath = (Resolve-Path "scripts/sign-windows.ps1").Path -replace '\\', '/' + $config = @{ + bundle = @{ + windows = @{ + signCommand = @{ + cmd = $pwshPath + args = @("-File", $scriptPath, "%1") + } + } } - } - } - EOF - echo "SIGNING_ARGS=--config signing.conf.json" >> "$GITHUB_ENV" + } | ConvertTo-Json -Depth 10 + $config | Set-Content signing.conf.json + Write-Host "signing.conf.json:" + Get-Content signing.conf.json + Add-Content -Path $env:GITHUB_ENV -Value "SIGNING_ARGS=--config signing.conf.json" - uses: tauri-apps/tauri-action@v0 env: From 457d746cf635c1a8d796c126407109db4303ff6b Mon Sep 17 00:00:00 2001 From: Michael Suchacz <203725896+ibetitsmike@users.noreply.github.com> Date: Thu, 5 Mar 2026 07:28:48 +0000 Subject: [PATCH 2/2] fix: add diagnostic logging to Windows sign script for Tauri bundler Tauri's bundler output_ok() discards subprocess stdout/stderr when the sign command exits non-zero, making failures invisible. The sign script has been running and failing silently for three releases. Changes: - sign-windows.ps1: Add Start-Transcript file logging, validate all prerequisites (java, jsign jar, certificate, env vars) with explicit error messages before attempting to sign - release.yml: Add RUST_LOG=debug for bundler-side logging, add post-failure step to dump the sign script transcript log --- .github/workflows/release.yml | 27 +++++++++++++ scripts/sign-windows.ps1 | 74 ++++++++++++++++++++++++++++++++--- 2 files changed, 96 insertions(+), 5 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d063b1c..71135d5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -110,6 +110,9 @@ jobs: - uses: tauri-apps/tauri-action@v0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # Enable bundler debug logging — sign command stdout/stderr is + # swallowed on failure; RUST_LOG surfaces the command invocation. + RUST_LOG: tauri_bundler=debug # macOS signing & notarization (optional — skipped if not set) APPLE_CERTIFICATE: ${{ secrets.MACOS_CERTIFICATE }} APPLE_CERTIFICATE_PASSWORD: ${{ secrets.MACOS_CERTIFICATE_PWD }} @@ -132,3 +135,27 @@ jobs: releaseDraft: true prerelease: false args: ${{ matrix.args }} ${{ env.SIGNING_ARGS }} + + # Dump sign script log on failure — Tauri bundler swallows subprocess + # stdout/stderr when the sign command exits non-zero, making failures + # invisible. The script writes a transcript to $RUNNER_TEMP/sign-windows.log. + - name: Dump signing log on failure + if: failure() && matrix.platform == 'windows-latest' + shell: pwsh + run: | + $logFile = Join-Path $env:RUNNER_TEMP "sign-windows.log" + if (Test-Path $logFile) { + Write-Host "=== sign-windows.log ===" + Get-Content $logFile + Write-Host "=== end sign-windows.log ===" + } else { + Write-Host "No sign-windows.log found at $logFile" + Write-Host "Sign script may not have been invoked, or RUNNER_TEMP differs." + Write-Host "Checking TEMP fallback..." + $fallback = Join-Path $env:TEMP "sign-windows.log" + if (Test-Path $fallback) { + Get-Content $fallback + } else { + Write-Host "No log file found at $fallback either." + } + } diff --git a/scripts/sign-windows.ps1 b/scripts/sign-windows.ps1 index bdb5832..c7b407c 100644 --- a/scripts/sign-windows.ps1 +++ b/scripts/sign-windows.ps1 @@ -3,6 +3,10 @@ # # Called by Tauri as: pwsh -File scripts/sign-windows.ps1 # +# NOTE: Tauri's bundler swallows stdout/stderr from sign commands on failure +# (output_ok() discards output on non-zero exit). All diagnostic output is +# tee'd to a log file so a post-failure workflow step can dump it. +# # Required environment variables: # JSIGN_PATH - Path to jsign JAR file # EV_KEYSTORE - GCP Cloud KMS keystore URL @@ -16,9 +20,20 @@ param( [string]$FilePath ) +# Log to file since Tauri bundler discards subprocess output on failure +$logDir = if ($env:RUNNER_TEMP) { $env:RUNNER_TEMP } else { $env:TEMP } +$logFile = Join-Path $logDir "sign-windows.log" +Start-Transcript -Path $logFile -Append -Force | Out-Null + +Write-Host "=== sign-windows.ps1 started at $(Get-Date -Format o) ===" +Write-Host "FilePath: $FilePath" +Write-Host "PID: $PID" +Write-Host "PowerShell: $($PSVersionTable.PSVersion)" + # Check if signing is configured if (-not $env:JSIGN_PATH -or -not $env:EV_KEYSTORE) { Write-Host "Windows code signing not configured - skipping $FilePath" + Stop-Transcript | Out-Null exit 0 } @@ -33,10 +48,47 @@ $requiredVars = @( ) foreach ($varName in $requiredVars) { - if (-not [System.Environment]::GetEnvironmentVariable($varName)) { + $val = [System.Environment]::GetEnvironmentVariable($varName) + if (-not $val) { Write-Error "Missing required environment variable: $varName" + Stop-Transcript | Out-Null exit 1 } + # Log presence without leaking secrets + $display = if ($varName -eq "GCLOUD_ACCESS_TOKEN") { "***($($val.Length) chars)" } else { $val } + Write-Host "${varName}: $display" +} + +# Verify file exists +if (-not (Test-Path $FilePath)) { + Write-Error "File not found: $FilePath" + Stop-Transcript | Out-Null + exit 1 +} +Write-Host "File exists: $FilePath ($($(Get-Item $FilePath).Length) bytes)" + +# Verify java is available +$javaCmd = Get-Command java -ErrorAction SilentlyContinue +if (-not $javaCmd) { + Write-Error "java not found in PATH" + Write-Host "PATH: $env:PATH" + Stop-Transcript | Out-Null + exit 1 +} +Write-Host "Java: $($javaCmd.Source)" + +# Verify jsign jar exists +if (-not (Test-Path $env:JSIGN_PATH)) { + Write-Error "jsign jar not found: $env:JSIGN_PATH" + Stop-Transcript | Out-Null + exit 1 +} + +# Verify certificate exists +if (-not (Test-Path $env:EV_CERTIFICATE_PATH)) { + Write-Error "Certificate file not found: $env:EV_CERTIFICATE_PATH" + Stop-Transcript | Out-Null + exit 1 } Write-Host "Signing $FilePath with EV certificate..." @@ -53,10 +105,22 @@ $jsignArgs = @( $FilePath ) -& java @jsignArgs -if ($LASTEXITCODE -ne 0) { - Write-Error "Failed to sign $FilePath (exit code: $LASTEXITCODE)" - exit 1 +# Log the command (mask the access token) +$displayArgs = $jsignArgs.Clone() +$storepassIdx = [Array]::IndexOf($displayArgs, "--storepass") +if ($storepassIdx -ge 0 -and ($storepassIdx + 1) -lt $displayArgs.Length) { + $displayArgs[$storepassIdx + 1] = "***" +} +Write-Host "Running: java $($displayArgs -join ' ')" + +& java @jsignArgs 2>&1 | ForEach-Object { Write-Host $_ } +$exitCode = $LASTEXITCODE + +if ($exitCode -ne 0) { + Write-Error "Failed to sign $FilePath (exit code: $exitCode)" + Stop-Transcript | Out-Null + exit $exitCode } Write-Host "Successfully signed $FilePath" +Stop-Transcript | Out-Null