Fix packaged Windows desktop startup by preserving Node-safe runtime dependencies and dashboard registry assets. - Externalize Electron main/preload npm packages so CommonJS updater dependencies load natively. - Load the dashboard plugin registry manifest through file IO and copy it into dashboard server dist from all build paths. - Split Windows NSIS and portable artifact names and verify required Electron runtime resources in CI. - Cover the packaging/runtime invariants with desktop and dashboard regression tests. Files changed: .changeset/fn-7360-desktop-windows.md | 7 +++ .github/workflows/desktop-windows.yml | 21 ++++++++ packages/dashboard/package.json | 2 +- .../src/__tests__/plugin-registry-dist.test.ts | 32 ++++++++++++ .../src/__tests__/routes-plugin-registry.test.ts | 10 ++-- packages/dashboard/src/plugin-routes.ts | 27 +++++++++- packages/desktop/README.md | 5 +- packages/desktop/electron-builder.yml | 9 ++++ packages/desktop/scripts/build.ts | 29 ++++++++-- packages/desktop/scripts/workspace-tools.ts | 4 ++ .../desktop/src/__tests__/build-bundling.test.ts | 61 ++++++++++++++++++++++ .../src/__tests__/electron-builder-config.test.ts | 15 ++++++ packages/desktop/src/__tests__/ipc.test.ts | 15 ++++++ .../desktop/src/__tests__/local-runtime.test.ts | 20 +++++++ 14 files changed, 247 insertions(+), 10 deletions(-) Fusion-Task-Id: FN-7360 Fusion-Task-Lineage: a2d88130-c24f-43e2-932a-1e174b6afa35 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
91 lines
4.0 KiB
YAML
91 lines
4.0 KiB
YAML
name: Desktop Windows Build
|
|
|
|
on:
|
|
workflow_dispatch:
|
|
|
|
jobs:
|
|
build-windows-exe:
|
|
runs-on: windows-latest
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Setup pnpm
|
|
uses: pnpm/action-setup@v4
|
|
|
|
- name: Setup Node.js
|
|
uses: actions/setup-node@v4
|
|
with:
|
|
node-version: 22
|
|
cache: pnpm
|
|
|
|
- name: Install dependencies
|
|
run: pnpm install --frozen-lockfile
|
|
|
|
- name: Build desktop package
|
|
run: pnpm --filter @fusion/desktop build
|
|
|
|
# Code-signing hardening is intentionally deferred to FN-5592.
|
|
- name: Package signed Windows EXE
|
|
if: ${{ env.WINDOWS_CERTIFICATE_BASE64 != '' }}
|
|
run: pnpm --filter @fusion/desktop exec electron-builder --win --x64 --arm64 --publish never
|
|
env:
|
|
WINDOWS_CERTIFICATE_BASE64: ${{ secrets.WINDOWS_CERTIFICATE_BASE64 }}
|
|
CSC_LINK: ${{ secrets.WINDOWS_CERTIFICATE_BASE64 }}
|
|
CSC_KEY_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
|
|
CSC_IDENTITY_AUTO_DISCOVERY: "false"
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- name: Package unsigned Windows EXE
|
|
if: ${{ env.WINDOWS_CERTIFICATE_BASE64 == '' }}
|
|
run: pnpm --filter @fusion/desktop exec electron-builder --win --x64 --arm64 --publish never
|
|
env:
|
|
WINDOWS_CERTIFICATE_BASE64: ${{ secrets.WINDOWS_CERTIFICATE_BASE64 }}
|
|
CSC_IDENTITY_AUTO_DISCOVERY: "false"
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- name: Verify signed artifacts
|
|
if: ${{ env.WINDOWS_CERTIFICATE_BASE64 != '' }}
|
|
shell: pwsh
|
|
env:
|
|
WINDOWS_CERTIFICATE_BASE64: ${{ secrets.WINDOWS_CERTIFICATE_BASE64 }}
|
|
run: |
|
|
$exes = Get-ChildItem packages/desktop/dist-electron -Filter *.exe
|
|
if ($exes.Count -eq 0) { Write-Error "No EXE artifacts produced"; exit 1 }
|
|
foreach ($exe in $exes) {
|
|
$sig = Get-AuthenticodeSignature $exe.FullName
|
|
Write-Host "$($exe.Name): $($sig.Status)"
|
|
if ($sig.Status -ne 'Valid') { Write-Error "Signature invalid: $($exe.Name) ($($sig.Status))"; exit 1 }
|
|
}
|
|
|
|
- name: Verify Windows runtime resources
|
|
shell: pwsh
|
|
run: |
|
|
# FNXC:WindowsDesktopPackaging 2026-07-01-08:08:
|
|
# The Windows app must install Electron's root .pak runtime resources;
|
|
# missing chrome_100_percent.pak, chrome_200_percent.pak, or resources.pak
|
|
# leaves Fusion.exe unable to start even when the NSIS installer succeeds.
|
|
$requiredResources = @('chrome_100_percent.pak', 'chrome_200_percent.pak', 'resources.pak')
|
|
$unpackedRoots = Get-ChildItem packages/desktop/dist-electron -Directory -Filter 'win*-unpacked'
|
|
if ($unpackedRoots.Count -eq 0) { Write-Error "No win-unpacked directory produced"; exit 1 }
|
|
foreach ($root in $unpackedRoots) {
|
|
foreach ($resource in $requiredResources) {
|
|
$resourcePath = Join-Path $root.FullName $resource
|
|
if (!(Test-Path $resourcePath)) { Write-Error "Missing Electron runtime resource: $resourcePath"; exit 1 }
|
|
}
|
|
}
|
|
$nsis = Get-ChildItem packages/desktop/dist-electron -Filter 'Fusion-*-win-*.exe' | Where-Object { $_.Name -notmatch '-portable\.exe$' }
|
|
$portable = Get-ChildItem packages/desktop/dist-electron -Filter 'Fusion-*-win-*-portable.exe'
|
|
if ($nsis.Count -eq 0) { Write-Error "No NSIS installer artifact produced"; exit 1 }
|
|
if ($portable.Count -eq 0) { Write-Error "No portable EXE artifact produced"; exit 1 }
|
|
|
|
# Automated publish is intentionally deferred to FN-5593.
|
|
# Keep a single artifact; filenames include -x64 / -arm64 so both arches are captured.
|
|
- name: Upload Windows artifacts
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: fusion-desktop-windows
|
|
path: |
|
|
packages/desktop/dist-electron/*.exe
|
|
packages/desktop/dist-electron/*.blockmap
|