Files
fusion/.github/workflows/desktop-windows.yml
gsxdsm abd596b700 fix: pack full desktop dependency closure + resolve bun/desktop plugin loading on Windows
Desktop "Local" mode crashed with ERR_MODULE_NOT_FOUND because electron-builder's
pnpm collector drops `deduped` subtrees, so engine's transitive closure
(@modelcontextprotocol/sdk, pi-ai provider SDKs, etc.) was never packed. Stage the
complete flat prod closure with `pnpm deploy --legacy --config.node-linker=hoisted`
and package it via `electron-builder --projectDir deploy`, bypassing the lossy
collector entirely.

Also make the dashboard-imported example plugins loadable under plain Node (the
Electron main runtime): cursor/droid/roadmap now expose compiled `dist` on the
`import` condition (keeping `source`→src for the bun CLI) and are built during the
desktop build. Add `source` conditions to paperclip/agent-browser/even-cards/
even-realities-glasses/whatsapp-chat so the bun `--conditions=source` Windows CLI
compile resolves them from source.

Validated on macOS: @fusion/core|engine|dashboard import cleanly from the staged
deploy; packing yields a complete 705-package asar; bun-windows-x64 cross-compiles
with all plugin dist removed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 20:40:02 -07:00

101 lines
4.6 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
# FNXC:WindowsDesktopPackaging 2026-07-01-19:45:
# Mirror release.yml: build every workspace package's tsc dist (incl.
# @fusion/core and @fusion/engine, which are gitignored) before packaging.
# Without this the embedded Local runtime's `import("@fusion/engine")`
# resolves to an empty dist and the app crashes with ERR_MODULE_NOT_FOUND.
# `@fusion/desktop build` now also self-builds these, so this is belt-and-
# suspenders parity that additionally covers any other workspace runtime dep.
- name: Build workspace
run: pnpm build
- 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 --projectDir deploy --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 --projectDir deploy --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