diff --git a/.github/workflows/release-tauri.yml b/.github/workflows/release-tauri.yml index 9ae2c441..8192bc96 100644 --- a/.github/workflows/release-tauri.yml +++ b/.github/workflows/release-tauri.yml @@ -300,8 +300,10 @@ jobs: throw "Required WiX object missing: $p — tauri build aborted before candle ran. Check the Build (Windows) step log." } } - $light = (Get-ChildItem "$env:LOCALAPPDATA\tauri\WixTools314\light.exe" -ErrorAction SilentlyContinue | Select-Object -First 1).FullName - if (-not $light) { throw "WiX light.exe not found in $env:LOCALAPPDATA\tauri\WixTools314" } + $light = Get-ChildItem "$env:LOCALAPPDATA\tauri\WixTools*\light.exe" -ErrorAction SilentlyContinue | + Sort-Object FullName | + Select-Object -Last 1 -ExpandProperty FullName + if (-not $light) { throw "WiX light.exe not found under $env:LOCALAPPDATA\tauri\WixTools*" } $version = (Get-Content src-tauri\tauri.conf.json -Raw | ConvertFrom-Json).version $bundleDir = Join-Path $appRoot 'src-tauri\target\release\bundle\msi' New-Item -ItemType Directory -Force -Path $bundleDir | Out-Null diff --git a/openless-all/app/scripts/windows-package-msvc.ps1 b/openless-all/app/scripts/windows-package-msvc.ps1 index baff9663..4eecf92e 100644 --- a/openless-all/app/scripts/windows-package-msvc.ps1 +++ b/openless-all/app/scripts/windows-package-msvc.ps1 @@ -93,9 +93,16 @@ function Find-VsDevCmd { } function Find-WixTool($Name) { - $tauriWixTool = Join-Path $env:LOCALAPPDATA "tauri\WixTools314\$Name" - if (Test-Path $tauriWixTool) { - return (Resolve-Path $tauriWixTool).Path + $tauriWixRoot = Join-Path $env:LOCALAPPDATA "tauri" + if (Test-Path $tauriWixRoot) { + $tauriWixTools = Get-ChildItem -LiteralPath $tauriWixRoot -Directory -Filter "WixTools*" -ErrorAction SilentlyContinue | + Sort-Object @{ Expression = { if ($_.Name -match '^WixTools(\d+)$') { [int]$Matches[1] } else { -1 } }; Descending = $true }, @{ Expression = "Name"; Descending = $true } + foreach ($toolDir in $tauriWixTools) { + $tauriWixTool = Join-Path $toolDir.FullName $Name + if (Test-Path $tauriWixTool) { + return (Resolve-Path $tauriWixTool).Path + } + } } $cmd = Get-Command $Name -ErrorAction SilentlyContinue @@ -103,7 +110,7 @@ function Find-WixTool($Name) { return $cmd.Source } - throw "$Name not found. Run the Tauri MSI build once so the WiX tools are installed." + throw "$Name not found. Run the Tauri MSI build once so a WiX tools directory is installed under $tauriWixRoot." } function Get-PackageVersion { diff --git a/openless-all/app/scripts/windows-package-msvc.test.mjs b/openless-all/app/scripts/windows-package-msvc.test.mjs index d5a17eed..ce5aa4ec 100644 --- a/openless-all/app/scripts/windows-package-msvc.test.mjs +++ b/openless-all/app/scripts/windows-package-msvc.test.mjs @@ -65,6 +65,10 @@ for (const fragment of requiredFragments) { assert.match(script, /\[switch\]\$SkipRustInstall/, "script should support opting out of Rust installation"); assert.match(script, /\[switch\]\$SkipNpmCi/, "script should support reusing existing node_modules"); assert.match(script, /\[switch\]\$CleanArtifacts/, "script should support cleaning the output directory"); +assert.doesNotMatch(script, /WixTools314/, "MSVC packaging must not hard-code a single Tauri WiX tools version"); +assert.doesNotMatch(ciWorkflow, /WixTools314/, "CI MSI repair must not hard-code a single Tauri WiX tools version"); +assert.match(script, /-Filter "WixTools\*"/, "MSVC packaging should discover Tauri WiX tools by WixTools* glob"); +assert.match(ciWorkflow, /WixTools\*\\light\.exe/, "CI MSI repair should discover Tauri WiX tools by WixTools* glob"); assert.match(imeBuild, /\[string\]\$OutputDirectory/, "IME build should support a package-specific output directory"); assert.match(imeBuild, /\[string\]\$IntermediateDirectory/, "IME build should support a package-specific intermediate directory"); @@ -120,11 +124,10 @@ assert.match(wixFragment, /UnregisterOpenLessImeX86/, "MSI should unregister x86 assert.match(nsisHook, /NSIS_HOOK_PREINSTALL/, "NSIS should copy IME DLLs before install completes"); assert.match(nsisHook, /NSIS_HOOK_POSTINSTALL/, "NSIS should register IME DLLs after files are installed"); assert.match(nsisHook, /NSIS_HOOK_PREUNINSTALL/, "NSIS should unregister IME DLLs before uninstall removes them"); -assert.match(nsisHook, /\$%OPENLESS_IME_DLL_X64%/, "NSIS should consume the CI-built x64 IME DLL"); -assert.match(nsisHook, /\$%OPENLESS_IME_DLL_X86%/, "NSIS should consume the CI-built x86 IME DLL"); -assert.match(nsisHook, /SetOutPath "\$INSTDIR\\windows-ime\\x64"/, "NSIS should install the x64 IME DLL beside the app"); -assert.match(nsisHook, /SetOutPath "\$INSTDIR\\windows-ime\\x86"/, "NSIS should install the x86 IME DLL beside the app"); -assert.match(nsisHook, /File \/oname=OpenLessIme\.dll/, "NSIS should embed OpenLessIme.dll in the installer"); +assert.match(nsisHook, /OPENLESS_IME_STAGE_AND_REPLACE "x64" "OPENLESS_IME_DLL_X64"/, "NSIS should consume the CI-built x64 IME DLL"); +assert.match(nsisHook, /OPENLESS_IME_STAGE_AND_REPLACE "x86" "OPENLESS_IME_DLL_X86"/, "NSIS should consume the CI-built x86 IME DLL"); +assert.match(nsisHook, /SetOutPath "\$INSTDIR\\windows-ime\\\$\{PLATFORM_DIR\}"/, "NSIS should install the IME DLL beside the app by platform"); +assert.match(nsisHook, /File \/oname=OpenLessIme\.dll\.new "\$%\$\{ENV_VAR\}%"/, "NSIS should embed OpenLessIme.dll in the installer"); assert.match(nsisHook, /Sysnative\\regsvr32\.exe/, "NSIS should use 64-bit regsvr32 for the x64 IME"); assert.match(nsisHook, /SysWOW64\\regsvr32\.exe/, "NSIS should use 32-bit regsvr32 for the x86 IME"); assert.match(nsisHook, /System32\\regsvr32\.exe[\s\S]*windows-ime\\x86\\OpenLessIme\.dll/, "NSIS should use System32 regsvr32 for the x86 IME on 32-bit Windows");