From 11ff1c29a612263083a2b73e2d85663db208e488 Mon Sep 17 00:00:00 2001 From: t8y2 <1156263951@qq.com> Date: Wed, 2 Sep 2026 21:08:39 +0800 Subject: [PATCH] fix(ci): guard win7 webview2 loader link against sccache v0.6.0 shipped a win7/Server 2012 R2 installer whose dbx.exe statically linked a WebView2 loader >= 1.0.1054.31 instead of the pinned 1.0.902.49, failing on kernel 6.3 with ERROR_NOT_SUPPORTED. The loader patch rewrites a file inside the cargo registry, which no compile cache can observe, so the win7 release job stops using sccache until the loader is vendored, and a binary audit now rejects any dbx.exe carrying post-1.0.902.49 loader strings. --- .../scripts/assert-webview2-win7-loader.ps1 | 54 +++++++++++++++++++ .github/workflows/ci.yml | 5 ++ .github/workflows/release.yml | 48 ++++------------- .../windowsInstallerTemplate.spec.ts | 25 +++++++++ 4 files changed, 94 insertions(+), 38 deletions(-) create mode 100644 .github/scripts/assert-webview2-win7-loader.ps1 diff --git a/.github/scripts/assert-webview2-win7-loader.ps1 b/.github/scripts/assert-webview2-win7-loader.ps1 new file mode 100644 index 0000000000..e755f003e6 --- /dev/null +++ b/.github/scripts/assert-webview2-win7-loader.ps1 @@ -0,0 +1,54 @@ +[CmdletBinding()] +param( + [Parameter(Mandatory = $true)] + [string]$BinaryPath +) + +Set-StrictMode -Version Latest +$ErrorActionPreference = "Stop" + +# The Win7 / Server 2012 R2 bundle must statically link the WebView2 loader from +# SDK 1.0.902.49, the last one verified to work on kernel 6.1/6.3. Loader +# 1.0.1054.31 and everything newer fail on Server 2012 R2 with +# ERROR_NOT_SUPPORTED (0x80070032, MicrosoftEdge/WebView2Feedback#2025) and make +# the app show "Could not find the WebView2 Runtime". Those loaders carry error +# strings that 1.0.902.49 does not, so any of the markers below appearing in +# dbx.exe proves the pinned loader was not the one linked. The PE import audit +# cannot catch this: 1.0.1054.31 imports nothing newer than 1.0.902.49. +$loaderMarkers = @( + "Failed to find the Web", + "Failed to find the app", + "Failed to find an inst", + "WebView2: Failed to find an installed" +) + +if (!(Test-Path -LiteralPath $BinaryPath -PathType Leaf)) { + throw "Win7 WebView2 loader audit target does not exist: $BinaryPath" +} + +$resolvedPath = (Resolve-Path -LiteralPath $BinaryPath).Path +# Map every byte to one character so the ASCII needle search cannot miss on +# arbitrary binary content. +$latin1 = [System.Text.Encoding]::GetEncoding(28591) +$content = $latin1.GetString([System.IO.File]::ReadAllBytes($resolvedPath)) + +$violations = @() +foreach ($marker in $loaderMarkers) { + if ($content.Contains($marker)) { + $violations += $marker + } +} + +if ($violations.Count -gt 0) { + $summary = $violations -join "`n" + throw @" +dbx.exe contains WebView2 loader strings newer than the pinned 1.0.902.49: +$summary + +A loader >= 1.0.1054.31 was linked instead of the prepared one and will fail on +Server 2012 R2 with ERROR_NOT_SUPPORTED. Do not ship this binary: rebuild the +win7 target and investigate how the registry loader patch was bypassed. +"@ +} + +Write-Host "Win7 WebView2 loader audit passed: no post-1.0.902.49 loader markers in $resolvedPath" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9a6c8434e4..5a66a09b77 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -258,6 +258,10 @@ jobs: shell: pwsh run: ./.github/scripts/assert-win7-pe-compat.ps1 -BinaryPath target/x86_64-win7-windows-msvc/release/dbx.exe + - name: Audit Win7 WebView2 loader markers + shell: pwsh + run: ./.github/scripts/assert-webview2-win7-loader.ps1 -BinaryPath target/x86_64-win7-windows-msvc/release/dbx.exe + - name: Bundle Windows 7 fixed-runtime installer shell: pwsh run: | @@ -698,6 +702,7 @@ jobs: - '.github/workflows/update-nix-pnpm-hash.yml' windows_win7_bundle: - '.github/scripts/assert-win7-pe-compat.ps1' + - '.github/scripts/assert-webview2-win7-loader.ps1' - '.github/scripts/assert-win7-installer-content.ps1' - '.github/scripts/assert-webview2-win7-runtime.ps1' - '.github/scripts/prepare-webview2-win7-loader.ps1' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 542c151d0f..e9dd00a55e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -551,10 +551,14 @@ jobs: needs: release-ready runs-on: windows-2022 environment: release-signing + # No sccache here: the loader patch rewrites a file inside the cargo + # registry, which is invisible to any compile cache. v0.6.0 shipped a + # binary linked against the wrong (>= 1.0.1054.31) WebView2 loader even + # though the patched 1.0.902.49 loader was verified on disk, so caching is + # disabled for this target until the patch is vendored into the source + # tree. env: CARGO_INCREMENTAL: "0" - RUSTC_WRAPPER: sccache - SCCACHE_GHA_ENABLED: ${{ secrets.SCCACHE_S3_BUCKET == '' && 'true' || 'false' }} RUSTFLAGS: -C debuginfo=line-tables-only -C target-feature=+crt-static VSIGN_CERT_HASH: ${{ vars.VSIGN_CERT_HASH }} VSIGN_OPERATOR_SHA1: ${{ vars.VSIGN_OPERATOR_SHA1 }} @@ -580,36 +584,6 @@ jobs: toolchain: nightly-2026-07-22 components: rust-src - - name: Setup sccache - uses: mozilla-actions/sccache-action@9e7fa8a12102821edf02ca5dbea1acd0f89a2696 # v0.0.10 - with: - version: "v0.10.0" - - - name: Configure S3 sccache - if: env.SCCACHE_GHA_ENABLED != 'true' - shell: bash - env: - CACHE_BUCKET: ${{ secrets.SCCACHE_S3_BUCKET }} - CACHE_ENDPOINT: ${{ secrets.SCCACHE_S3_ENDPOINT }} - CACHE_REGION: ${{ secrets.SCCACHE_S3_REGION }} - CACHE_KEY_PREFIX: ${{ secrets.SCCACHE_S3_KEY_PREFIX }} - CACHE_ACCESS_KEY_ID: ${{ secrets.SCCACHE_S3_ACCESS_KEY_ID }} - CACHE_SECRET_ACCESS_KEY: ${{ secrets.SCCACHE_S3_SECRET_ACCESS_KEY }} - run: | - { - echo "SCCACHE_BUCKET=${CACHE_BUCKET}" - echo "SCCACHE_ENDPOINT=${CACHE_ENDPOINT}" - echo "SCCACHE_REGION=${CACHE_REGION}" - echo "SCCACHE_S3_KEY_PREFIX=${CACHE_KEY_PREFIX}" - echo "SCCACHE_S3_USE_SSL=true" - echo "AWS_ACCESS_KEY_ID=${CACHE_ACCESS_KEY_ID}" - echo "AWS_SECRET_ACCESS_KEY=${CACHE_SECRET_ACCESS_KEY}" - # Linking, bundling, and signing run for 30+ minutes after the last - # rustc call; the server's 10-minute default idle timeout would - # exit first and zero the counters shown by "Show sccache stats". - echo "SCCACHE_IDLE_TIMEOUT=0" - } >> "$GITHUB_ENV" - - name: Prepare Win7-compatible WebView2 loader shell: pwsh run: ./.github/scripts/prepare-webview2-win7-loader.ps1 @@ -644,6 +618,10 @@ jobs: shell: pwsh run: ./.github/scripts/assert-win7-pe-compat.ps1 -BinaryPath target/x86_64-win7-windows-msvc/release/dbx.exe + - name: Audit Win7 WebView2 loader markers + shell: pwsh + run: ./.github/scripts/assert-webview2-win7-loader.ps1 -BinaryPath target/x86_64-win7-windows-msvc/release/dbx.exe + - name: Setup TrustAsia VSign shell: pwsh env: @@ -691,12 +669,6 @@ jobs: gh release upload "${env:GITHUB_REF_NAME}" $offlineName $checksumName ` --repo "${env:GITHUB_REPOSITORY}" --clobber - - name: Show sccache stats - if: always() - continue-on-error: true - shell: bash - run: ${SCCACHE_PATH} --show-stats - - name: Remove temporary VSign files if: always() shell: pwsh diff --git a/apps/desktop/src/lib/__tests__/windowsInstallerTemplate.spec.ts b/apps/desktop/src/lib/__tests__/windowsInstallerTemplate.spec.ts index 4fc834d2c3..7d61c3e975 100644 --- a/apps/desktop/src/lib/__tests__/windowsInstallerTemplate.spec.ts +++ b/apps/desktop/src/lib/__tests__/windowsInstallerTemplate.spec.ts @@ -7,6 +7,7 @@ const template = readFileSync(resolve(process.cwd(), "src-tauri/windows/nsis/ins const win7Config = JSON.parse(readFileSync(resolve(process.cwd(), "src-tauri/tauri.webview2-win7-fixed.conf.json"), "utf8")); const win7RuntimeScript = readFileSync(resolve(process.cwd(), ".github/scripts/prepare-webview2-win7-runtime.ps1"), "utf8"); const win7PeAuditScript = readFileSync(resolve(process.cwd(), ".github/scripts/assert-win7-pe-compat.ps1"), "utf8"); +const win7LoaderAuditScript = readFileSync(resolve(process.cwd(), ".github/scripts/assert-webview2-win7-loader.ps1"), "utf8"); const win7RuntimeProbeScript = readFileSync(resolve(process.cwd(), ".github/scripts/assert-webview2-win7-runtime.ps1"), "utf8"); const win7InstallerAuditScript = readFileSync(resolve(process.cwd(), ".github/scripts/assert-win7-installer-content.ps1"), "utf8"); const appCargoToml = readFileSync(resolve(process.cwd(), "src-tauri/Cargo.toml"), "utf8"); @@ -127,6 +128,30 @@ describe("Windows 7 fixed WebView2 runtime bundle", () => { expect(win7PeAuditScript).toContain("dumpbin.exe"); }); + it("audits the linked WebView2 loader in the final Win7 binary", () => { + expect(win7LoaderAuditScript).toContain('"Failed to find the Web"'); + expect(win7LoaderAuditScript).toContain('"Failed to find the app"'); + expect(win7LoaderAuditScript).toContain('"Failed to find an inst"'); + expect(win7LoaderAuditScript).toContain('"WebView2: Failed to find an installed"'); + expect(win7LoaderAuditScript).toContain("GetEncoding(28591)"); + expect(ciWorkflow).toContain("./.github/scripts/assert-webview2-win7-loader.ps1"); + expect(releaseWorkflow).toContain("./.github/scripts/assert-webview2-win7-loader.ps1"); + }); + + it("keeps compile caching away from the Win7 WebView2 loader patch", () => { + const releaseWin7Job = releaseWorkflow.slice(releaseWorkflow.indexOf(" build-windows-7-offline:"), releaseWorkflow.indexOf(" static-browser:")); + const ciWin7Job = ciWorkflow.slice(ciWorkflow.indexOf(" windows-win7-bundle:"), ciWorkflow.indexOf(" duckdb-windows-driver:")); + + // The loader patch rewrites a file inside the cargo registry, which no + // compile cache can see. v0.6.0 linked a >= 1.0.1054.31 loader despite the + // patched 1.0.902.49 one being verified on disk, so neither Win7 job may + // route rustc through sccache until the loader is vendored into the tree. + expect(releaseWin7Job).not.toContain("RUSTC_WRAPPER"); + expect(releaseWin7Job).not.toContain("sccache-action"); + expect(ciWin7Job).not.toContain("RUSTC_WRAPPER"); + expect(ciWin7Job).not.toContain("sccache-action"); + }); + it("probes the fixed runtime through the Win7-compatible loader", () => { expect(win7RuntimeProbeScript).toContain("GetAvailableCoreWebView2BrowserVersionString"); expect(win7RuntimeProbeScript).toContain('$ExpectedVersion = "109.0.1518.78"');