Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 32 additions & 15 deletions .github/workflows/release-tauri.yml
Original file line number Diff line number Diff line change
Expand Up @@ -429,21 +429,38 @@ jobs:
shell: pwsh
working-directory: 'openless-all/app'
run: |
$nsis = Get-ChildItem "src-tauri\target\release\bundle\nsis\*.exe" -ErrorAction Stop | Select-Object -First 1
if (-not $nsis) { throw "NSIS installer not found." }
powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\scripts\windows-ime-install-smoke.ps1 -InstallerPath $nsis.FullName -InstallerKind nsis
if ($LASTEXITCODE -ne 0) {
throw "NSIS installer smoke failed with exit $LASTEXITCODE"
}
if ($env:OPENLESS_SKIP_WINDOWS_MSI -eq '1') {
Write-Host "[ok] Skipping MSI smoke for beta release channel."
return
}
$msi = Get-ChildItem "src-tauri\target\release\bundle\msi\*.msi" -ErrorAction Stop | Select-Object -First 1
if (-not $msi) { throw "MSI installer not found." }
powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\scripts\windows-ime-install-smoke.ps1 -InstallerPath $msi.FullName -InstallerKind msi
if ($LASTEXITCODE -ne 0) {
throw "MSI installer smoke failed with exit $LASTEXITCODE"
# The disposable runner must not be shut down by MSI Restart Manager
# after the NSIS install/uninstall has loaded the TSF DLLs. /norestart
# suppresses an OS reboot, not Restart Manager application shutdown.
# Keep both real installer/registry checks; restore the machine policy.
$policy = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\Installer'
$policyName = 'DisableAutomaticApplicationShutdown'
$previous = (Get-ItemProperty -LiteralPath $policy -Name $policyName -ErrorAction SilentlyContinue).$policyName
try {
New-Item -Path $policy -Force | Out-Null
New-ItemProperty -LiteralPath $policy -Name $policyName -PropertyType DWord -Value 1 -Force | Out-Null
$nsis = Get-ChildItem "src-tauri\target\release\bundle\nsis\*.exe" -ErrorAction Stop | Select-Object -First 1
if (-not $nsis) { throw "NSIS installer not found." }
powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\scripts\windows-ime-install-smoke.ps1 -InstallerPath $nsis.FullName -InstallerKind nsis
if ($LASTEXITCODE -ne 0) {
throw "NSIS installer smoke failed with exit $LASTEXITCODE"
}
if ($env:OPENLESS_SKIP_WINDOWS_MSI -eq '1') {
Write-Host "[ok] Skipping MSI smoke for beta release channel."
return
}
$msi = Get-ChildItem "src-tauri\target\release\bundle\msi\*.msi" -ErrorAction Stop | Select-Object -First 1
if (-not $msi) { throw "MSI installer not found." }
powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\scripts\windows-ime-install-smoke.ps1 -InstallerPath $msi.FullName -InstallerKind msi
if ($LASTEXITCODE -ne 0) {
throw "MSI installer smoke failed with exit $LASTEXITCODE"
}
} finally {
if ($null -ne $previous) {
New-ItemProperty -LiteralPath $policy -Name $policyName -PropertyType DWord -Value $previous -Force | Out-Null
} else {
Remove-ItemProperty -LiteralPath $policy -Name $policyName -ErrorAction SilentlyContinue
}
}

- name: Disambiguate macOS updater bundle filename
Expand Down
11 changes: 11 additions & 0 deletions docs/releases/2.0.1-windows-ci-isolation-20261016.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# 2.0.1 Windows 安装器 CI 隔离

Stable 标签 `v2.0.1-tauri` 固定在 `33d17a4e`,精确源码 CI `38876378343` 及 main CI `38878764285` 均七项通过。macOS 两架构、Android 四 ABI 已构建、下载并核验;不重建这些资产。

桌面 run `38878773775` 两次 Windows job(`116900142784`、`116916344722`)都已生成 NSIS 和数字 MSI 版本的安装包;NSIS 安装、COM/TSF/后端注册检查及卸载通过。两次均在随后的 `msiexec /i ... /qn /norestart` 开始约 1 秒后收到 runner shutdown signal,MSI 检查被取消,未上传 Windows 资产。重复位置排除了继续盲目重跑的价值,符合 MSI Restart Manager 关闭持有 TSF 组件的 runner 进程的现象;日志不把它记录为已通过安装验收。

Microsoft 官方定义 `/norestart` 不等于禁止 Restart Manager 关闭应用。CI 在真实安装器 smoke 之前,临时将 `HKLM\Software\Policies\Microsoft\Windows\Installer` 的 DWORD `DisableAutomaticApplicationShutdown` 设为 1,禁止 Windows Installer 与 Restart Manager 交互,并在 finally 恢复原值/移除本次新增属性。该设置仅存在于可丢弃的 Windows CI 主机,不写入 MSI/NSIS,不改变用户电脑策略,不跳过安装、卸载、DLL 路径或任何 COM/TSF 注册检查。

来源:[DisableAutomaticApplicationShutdown](https://learn.microsoft.com/en-us/windows/win32/msi/disableautomaticapplicationshutdown)、[MSIRESTARTMANAGERCONTROL](https://learn.microsoft.com/en-us/windows/win32/msi/msirestartmanagercontrol)。官方 Markdown 已从 MicrosoftDocs/win32 对应 desktop-src/Msi 文件核对。

工作流与契约经 PR/CI 后,仅使用已存在的管理员/草稿/精确 tag 源码/七项 CI 守卫的 Windows-only repair 入口,对 `v2.0.1-tauri` 构建并验证。应用源码、版本与标签不变;最终仍须 Windows smoke 成功、全部资产与签名核验后才公开 Stable。
11 changes: 11 additions & 0 deletions openless-all/app/scripts/windows-msi-release-contract.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,17 @@ const publisher = steps.find((s) => s.uses?.startsWith('softprops/action-gh-rele
assert.equal(publisher.with.tag_name, '${{ env.OPENLESS_RELEASE_TAG }}');
assert.equal(publisher.with.draft, true);
assert.ok(steps.find((s) => s.name === 'Confirm repair target remains draft'));
const smoke = steps.find((s) => s.name === 'Verify Windows installers register TSF IME');
assert.equal(smoke.if, "matrix.platform == 'windows-latest'");
assert.match(smoke.run, /DisableAutomaticApplicationShutdown/);
assert.match(smoke.run, /-PropertyType DWord -Value 1 -Force/);
assert.ok(smoke.run.indexOf('-Value 1 -Force') < smoke.run.indexOf('-InstallerKind nsis'));
assert.match(smoke.run, /finally[\s\S]*-Value \$previous[\s\S]*Remove-ItemProperty/);
for (const kind of ['nsis', 'msi']) {
assert.match(smoke.run, new RegExp('-InstallerKind ' + kind));
assert.match(smoke.run, new RegExp(kind.toUpperCase() + ' installer smoke failed'));
}
assert.doesNotMatch(smoke.run, /continue-on-error|SkipUninstall|exit 0/);
const schema = JSON.parse(
readFileSync(
new URL('../node_modules/@tauri-apps/cli/config.schema.json', import.meta.url),
Expand Down
Loading