From f463276ca507c7500bb33aba923e37431ebefeae Mon Sep 17 00:00:00 2001 From: Palash Debnath <4178343+debpalash@users.noreply.github.com> Date: Mon, 7 Sep 2026 11:51:41 +0530 Subject: [PATCH] ci: validate both Windows MSI scopes with a tiny payload --- .github/workflows/ci.yml | 29 ++++++++++++ scripts/diagnose-windows-wix.ps1 | 79 ++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+) create mode 100644 scripts/diagnose-windows-wix.ps1 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1a1a5e78..c2420ab4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,6 +11,11 @@ on: push: branches: [main] workflow_dispatch: + inputs: + windows_wix_diagnostic: + description: Run only the tiny nonpublishing Windows MSI authoring diagnostic + type: boolean + default: false permissions: contents: read @@ -21,6 +26,7 @@ env: jobs: test: + if: ${{ !inputs.windows_wix_diagnostic }} name: Tests (backend + frontend) runs-on: ubuntu-22.04 env: @@ -189,6 +195,7 @@ jobs: # and `cargo test --lib` runs the shell's unit tests natively on each OS. # Full bundling stays in release.yml on tag push. tauri-cross-platform: + if: ${{ !inputs.windows_wix_diagnostic }} name: Tauri shell check (${{ matrix.label }}) needs: test strategy: @@ -289,6 +296,7 @@ jobs: # job above misses. Narrow scope (tests/smoke/ only) — full pytest stays # on Linux until Phase 1's INST-01 lands setuptools for WhisperX. smoke-matrix: + if: ${{ !inputs.windows_wix_diagnostic }} name: Smoke (${{ matrix.label }}) needs: test strategy: @@ -442,3 +450,24 @@ jobs: env: HF_HUB_OFFLINE: "1" HF_HUB_CACHE: ${{ runner.temp }}/worker-artifact-empty-hf-cache + + windows-wix-diagnostic: + name: Windows MSI authoring (no publishing) + needs: test + if: ${{ !cancelled() && (inputs.windows_wix_diagnostic || needs.test.result == 'success') }} + runs-on: windows-2022 + timeout-minutes: 15 + steps: + - uses: actions/checkout@v4 + - uses: oven-sh/setup-bun@v1 + - name: Bundle canonical system and per-user templates with a tiny payload + shell: pwsh + run: ./scripts/diagnose-windows-wix.ps1 + - name: Preserve verbose linker output and rendered authoring + if: always() + uses: actions/upload-artifact@v4 + with: + name: windows-wix-diagnostic + path: wix-diagnostic-artifacts/ + if-no-files-found: warn + retention-days: 3 diff --git a/scripts/diagnose-windows-wix.ps1 b/scripts/diagnose-windows-wix.ps1 new file mode 100644 index 00000000..d20833a5 --- /dev/null +++ b/scripts/diagnose-windows-wix.ps1 @@ -0,0 +1,79 @@ +# Nonpublishing diagnostic: compile a tiny executable and bundle both MSI scopes. +# Uses the actual repository template/renderer and Tauri's generated resources. +$ErrorActionPreference = 'Stop' +$repo = Split-Path -Parent $PSScriptRoot +$fixture = Join-Path $env:RUNNER_TEMP 'voicestudio-wix-diagnostic' +$artifacts = Join-Path $repo 'wix-diagnostic-artifacts' +$target = 'x86_64-pc-windows-msvc' +$lock = Get-Content "$repo/bun.lock" -Raw +$cliMatch = [regex]::Match($lock, '"@tauri-apps/cli":\s*\["@tauri-apps/cli@([^"\s]+)"') +if (-not $cliMatch.Success) { throw 'Cannot resolve the Tauri CLI version from bun.lock' } +$cliPackage = '@tauri-apps/cli@' + $cliMatch.Groups[1].Value +New-Item -ItemType Directory -Force -Path $fixture, $artifacts, "$fixture/src", "$fixture/resources/nested", "$fixture/binaries" | Out-Null +@' +[package] +name = "wix-diagnostic" +version = "0.0.0" +edition = "2021" +[workspace] +'@ | Set-Content -Encoding utf8 "$fixture/Cargo.toml" +'fn main() { println!("MSI authoring diagnostic only"); }' | Set-Content -Encoding utf8 "$fixture/src/main.rs" +'Nested resource payload' | Set-Content -Encoding utf8 "$fixture/resources/nested/payload.txt" +'Root resource payload' | Set-Content -Encoding utf8 "$fixture/resources/readme.txt" +Copy-Item "$repo/frontend/src-tauri/wix/main.wxs" "$fixture/system.wxs" +Copy-Item "$repo/frontend/src-tauri/icons/icon.ico" "$fixture/icon.ico" +$config = @{ + productName = 'VoiceStudio MSI Diagnostic' + version = '0.0.0' + identifier = 'com.debpalash.voicestudio.wixdiagnostic' + build = @{} + bundle = @{ + active = $true + targets = @('msi') + createUpdaterArtifacts = $false + icon = @('icon.ico') + resources = @('resources/**/*') + externalBin = @('binaries/helper') + windows = @{ + webviewInstallMode = @{ type = 'skip' } + wix = @{ template = 'system.wxs'; enableElevatedUpdateTask = $false } + } + } +} +$config | ConvertTo-Json -Depth 20 | Set-Content -Encoding utf8 "$fixture/tauri.conf.json" +Push-Location $fixture +try { + & cargo build --release --target $target + if ($LASTEXITCODE -ne 0) { throw 'Tiny diagnostic executable build failed' } + Copy-Item "$fixture/target/$target/release/wix-diagnostic.exe" "$fixture/binaries/helper-$target.exe" + $results = @{} + foreach ($scope in @('system', 'per-user')) { + if ($scope -eq 'per-user') { + & python "$repo/scripts/render-per-user-wix.py" --source "$fixture/system.wxs" --system-wxs "$fixture/target/$target/release/wix/x64/main.wxs" --output "$fixture/per-user.wxs" + if ($LASTEXITCODE -ne 0) { throw 'Per-user template rendering failed' } + Remove-Item "$fixture/target/$target/release/wix", "$fixture/target/$target/release/bundle" -Recurse -Force -ErrorAction SilentlyContinue + } + $scopeConfig = @{ + productName = "VoiceStudio MSI Diagnostic $scope" + bundle = @{ windows = @{ wix = @{ template = "$scope.wxs" } } } + } + $scopeConfig | ConvertTo-Json -Depth 20 | Set-Content -Encoding utf8 "$fixture/$scope.conf.json" + $log = Join-Path $artifacts "$scope.log" + $ErrorActionPreference = 'Continue' + & bun x --package $cliPackage tauri bundle -vv --target $target --bundles msi --config "$scope.conf.json" *> $log + $results[$scope] = $LASTEXITCODE + $ErrorActionPreference = 'Stop' + Get-Content $log + $capture = Join-Path $artifacts $scope + New-Item -ItemType Directory -Force -Path $capture | Out-Null + Get-ChildItem "$fixture/target" -Recurse -File | + Where-Object { $_.Extension -in @('.wxs', '.wxl', '.wixobj', '.wixpdb', '.msi') } | + Copy-Item -Destination $capture -Force + } + $results | ConvertTo-Json | Set-Content -Encoding utf8 "$artifacts/results.json" + if ($results.Values | Where-Object { $_ -ne 0 }) { + throw "MSI authoring failure; inspect wix-diagnostic-artifacts logs and rendered WiX" + } +} finally { + Pop-Location +}