Bumps [pnpm/action-setup](https://github.com/pnpm/action-setup) from 4 to 6. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/pnpm/action-setup/releases">pnpm/action-setup's releases</a>.</em></p> <blockquote> <h2>v6.0.0</h2> <p>Added support for pnpm <a href="https://github.com/pnpm/pnpm/releases/tag/v11.0.0-rc.0">v11</a>.</p> <h2>v5.0.0</h2> <p>Updated the action to use Node.js 24.</p> <h2>v4.4.0</h2> <p>Updated the action to use Node.js 24.</p> <h2>v4.3.0</h2> <h2>What's Changed</h2> <ul> <li>docs: fix the run_install example in the Readme by <a href="https://github.com/dreyks"><code>@dreyks</code></a> in <a href="https://redirect.github.com/pnpm/action-setup/pull/175">pnpm/action-setup#175</a></li> <li>chore: remove unused <code>@types/node-fetch</code> dependency by <a href="https://github.com/silverwind"><code>@silverwind</code></a> in <a href="https://redirect.github.com/pnpm/action-setup/pull/186">pnpm/action-setup#186</a></li> <li>Clarify that package_json_file is relative to GITHUB_WORKSPACE by <a href="https://github.com/chris-martin"><code>@chris-martin</code></a> in <a href="https://redirect.github.com/pnpm/action-setup/pull/184">pnpm/action-setup#184</a></li> <li>feat: store caching by <a href="https://github.com/jrmajor"><code>@jrmajor</code></a> in <a href="https://redirect.github.com/pnpm/action-setup/pull/188">pnpm/action-setup#188</a></li> <li>refactor: remove star imports by <a href="https://github.com/KSXGitHub"><code>@KSXGitHub</code></a> in <a href="https://redirect.github.com/pnpm/action-setup/pull/196">pnpm/action-setup#196</a></li> <li>fix(ci): exclude macos by <a href="https://github.com/KSXGitHub"><code>@KSXGitHub</code></a> in <a href="https://redirect.github.com/pnpm/action-setup/pull/197">pnpm/action-setup#197</a></li> </ul> <h2>New Contributors</h2> <ul> <li><a href="https://github.com/dreyks"><code>@dreyks</code></a> made their first contribution in <a href="https://redirect.github.com/pnpm/action-setup/pull/175">pnpm/action-setup#175</a></li> <li><a href="https://github.com/silverwind"><code>@silverwind</code></a> made their first contribution in <a href="https://redirect.github.com/pnpm/action-setup/pull/186">pnpm/action-setup#186</a></li> <li><a href="https://github.com/chris-martin"><code>@chris-martin</code></a> made their first contribution in <a href="https://redirect.github.com/pnpm/action-setup/pull/184">pnpm/action-setup#184</a></li> <li><a href="https://github.com/jrmajor"><code>@jrmajor</code></a> made their first contribution in <a href="https://redirect.github.com/pnpm/action-setup/pull/188">pnpm/action-setup#188</a></li> <li><a href="https://github.com/Boosted-Bonobo"><code>@Boosted-Bonobo</code></a> made their first contribution in <a href="https://redirect.github.com/pnpm/action-setup/pull/199">pnpm/action-setup#199</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/pnpm/action-setup/compare/v4.2.0...v4.3.0">https://github.com/pnpm/action-setup/compare/v4.2.0...v4.3.0</a></p> <h2>v4.2.0</h2> <p>When there's a <code>.npmrc</code> file at the root of the repository, pnpm will be fetched from the registry that is specified in that <code>.npmrc</code> file <a href="https://redirect.github.com/pnpm/action-setup/pull/179">#179</a></p> <h2>v4.1.0</h2> <p>Add support for <code>package.yaml</code> <a href="https://redirect.github.com/pnpm/action-setup/pull/156">#156</a>.</p> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="0ebf47130e"><code>0ebf471</code></a> fix: update pnpm to v11.7.0 (<a href="https://redirect.github.com/pnpm/action-setup/issues/267">#267</a>)</li> <li><a href="0e279bb959"><code>0e279bb</code></a> fix: update pnpm to 11.1.1 (<a href="https://redirect.github.com/pnpm/action-setup/issues/248">#248</a>)</li> <li><a href="3e835812ef"><code>3e83581</code></a> fix: drop patchPnpmEnv so standalone+self-update works on Windows (<a href="https://redirect.github.com/pnpm/action-setup/issues/258">#258</a>)</li> <li><a href="551b42e879"><code>551b42e</code></a> docs(README): fix <code>cache_dependency_path</code> type (<a href="https://redirect.github.com/pnpm/action-setup/issues/257">#257</a>)</li> <li><a href="739bfe42ca"><code>739bfe4</code></a> fix: self-update bootstrap to packageManager-pinned version (<a href="https://redirect.github.com/pnpm/action-setup/issues/233">#233</a>) (<a href="https://redirect.github.com/pnpm/action-setup/issues/256">#256</a>)</li> <li><a href="f61705d907"><code>f61705d</code></a> chore: add CODEOWNERS</li> <li><a href="7a5507b117"><code>7a5507b</code></a> fix: restore inputs from state in post (<a href="https://redirect.github.com/pnpm/action-setup/issues/255">#255</a>)</li> <li><a href="1155470f3e"><code>1155470</code></a> fix: honor devEngines.packageManager.onFail=error (<a href="https://redirect.github.com/pnpm/action-setup/issues/252">#252</a>) (<a href="https://redirect.github.com/pnpm/action-setup/issues/254">#254</a>)</li> <li><a href="91ab88e261"><code>91ab88e</code></a> fix: bin_dest output points to self-updated pnpm, not bootstrap (<a href="https://redirect.github.com/pnpm/action-setup/issues/249">#249</a>)</li> <li><a href="e578e19d19"><code>e578e19</code></a> fix: update pnpm to 11.0.4</li> <li>Additional commits viewable in <a href="https://github.com/pnpm/action-setup/compare/v4...v6">compare view</a></li> </ul> </details> <br /> [](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: gsxdsm <gsxdsm@users.noreply.github.com>
224 lines
12 KiB
YAML
224 lines
12 KiB
YAML
name: Desktop Windows Build
|
|
|
|
on:
|
|
workflow_dispatch:
|
|
inputs:
|
|
skip_pg_smoke:
|
|
description: "Skip the embedded-PG smoke (already covered by verify-elevated-restricted.yml)"
|
|
type: boolean
|
|
default: false
|
|
|
|
jobs:
|
|
build-windows-exe:
|
|
runs-on: windows-latest
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v7
|
|
|
|
- name: Setup pnpm
|
|
uses: pnpm/action-setup@v6
|
|
|
|
- name: Setup Node.js
|
|
uses: actions/setup-node@v7
|
|
with:
|
|
node-version: 22
|
|
cache: pnpm
|
|
|
|
- name: Install dependencies
|
|
run: pnpm install --frozen-lockfile
|
|
|
|
# FNXC:WindowsDesktopPackaging 2026-07-15-00:55:
|
|
# The embedded-PG smoke boots postgres under a non-admin helper user
|
|
# (fusion-pg). The FIRST Start-Process -Credential for that user loads its
|
|
# Windows profile hive (~10-20s), which would blow a test's 15s budget.
|
|
# Create the user and warm its profile once here, outside any test window;
|
|
# the launcher resets the user's password before each run, but the warmed
|
|
# profile persists, so every later launch is ~0.5s.
|
|
# FNXC:WindowsDesktopPackaging 2026-07-18-01:40:
|
|
# The smoke wedged a runner for 45+ min with Start-Process -Wait and no
|
|
# step timeout (baseline ~18 min). Cap it, and allow skipping it via
|
|
# dispatch input when the dedicated verify-elevated-restricted workflow
|
|
# already proves embedded PG on this ref — packaging does not depend on it.
|
|
- name: Prewarm embedded-PG helper user profile
|
|
if: ${{ !inputs.skip_pg_smoke }}
|
|
shell: pwsh
|
|
run: |
|
|
$user = "fusion-pg"
|
|
# Throwaway password for the ephemeral helper user (the launcher resets
|
|
# it before each run); generated at runtime to avoid a hardcoded literal.
|
|
$pass = "Fx9!" + ([guid]::NewGuid().ToString("N")) + "#kP"
|
|
net user $user $pass /add /y 2>&1 | Out-Null
|
|
$sec = ConvertTo-SecureString $pass -AsPlainText -Force
|
|
$cred = New-Object System.Management.Automation.PSCredential("$env:COMPUTERNAME\$user", $sec)
|
|
[void](Start-Process -FilePath cmd.exe -ArgumentList '/c','exit' -Credential $cred -Wait -WindowStyle Hidden)
|
|
Write-Host "prewarmed $user profile"
|
|
|
|
# FNXC:DesktopEmbeddedPostgres 2026-07-14-09:39:
|
|
# The manual Windows installer path must boot the same embedded database
|
|
# payload used by Local mode before it can publish an installer artifact.
|
|
# FNXC:WindowsDesktopPackaging 2026-07-15-02:40:
|
|
# The runner executes jobs elevated, and PostgreSQL refuses an elevated
|
|
# (admin) token. Run the WHOLE smoke AS the non-admin helper user
|
|
# (fusion-pg): the test process, its tmpdir() data dirs, AND postgres all
|
|
# run as fusion-pg, so postgres inherits a non-admin token and boots via
|
|
# the normal embedded-postgres path — no in-launcher Start-Process
|
|
# -Credential / staging / process-kill races.
|
|
- name: Smoke embedded Postgres on Windows
|
|
if: ${{ !inputs.skip_pg_smoke }}
|
|
timeout-minutes: 30
|
|
shell: pwsh
|
|
run: |
|
|
$user = "fusion-pg"
|
|
$pass = "Fx9!" + ([guid]::NewGuid().ToString("N")) + "#kP"
|
|
net user $user $pass /y 2>&1 | Out-Null
|
|
# FNXC:WindowsDesktopPackaging 2026-07-15-11:25:
|
|
# Full recursive grants on the workspace + pnpm store (proven green on
|
|
# win-pg-diag). Narrow grants miss pnpm resolution targets and exit 1
|
|
# with no useful signal. Capture the bat log so failures surface.
|
|
Write-Host "granting ACL (workspace + tooling) for $user..."
|
|
icacls $env:GITHUB_WORKSPACE /grant "*S-1-5-32-545:(OI)(CI)M" /T /C 2>&1 | Out-Null
|
|
if (Test-Path D:\.pnpm-store) {
|
|
icacls D:\.pnpm-store /grant "*S-1-5-32-545:(OI)(CI)RX" /T /C 2>&1 | Out-Null
|
|
}
|
|
icacls C:\Users\runneradmin /grant "*S-1-5-32-545:RX" /C 2>&1 | Out-Null
|
|
if (Test-Path C:\Users\runneradmin\setup-pnpm) {
|
|
icacls C:\Users\runneradmin\setup-pnpm /grant "*S-1-5-32-545:(OI)(CI)RX" /T /C 2>&1 | Out-Null
|
|
}
|
|
$nodeDir = Split-Path (Get-Command node).Source -Parent
|
|
icacls $nodeDir /grant "*S-1-5-32-545:(OI)(CI)RX" /T /C 2>&1 | Out-Null
|
|
# Traversable HOME/TEMP for the helper user (its tmpdir() lands here).
|
|
$h = "C:\fusionpg-home"
|
|
New-Item -ItemType Directory -Force -Path "$h\tmp" | Out-Null
|
|
icacls $h /grant "*S-1-5-32-545:(OI)(CI)F" /T /C 2>&1 | Out-Null
|
|
$pnpmDir = Split-Path (Get-Command pnpm).Source -Parent
|
|
$bat = Join-Path $h "smoke.bat"
|
|
$log = Join-Path $h "smoke.log"
|
|
Set-Content -Path $bat -Encoding ASCII -Value @(
|
|
"@echo off",
|
|
"set `"USERPROFILE=$h`"",
|
|
"set `"APPDATA=$h\AppData\Roaming`"",
|
|
"set `"LOCALAPPDATA=$h\AppData\Local`"",
|
|
"set `"TEMP=$h\tmp`"",
|
|
"set `"TMP=$h\tmp`"",
|
|
"set `"PATH=$nodeDir;$pnpmDir;%PATH%`"",
|
|
"cd /d $env:GITHUB_WORKSPACE",
|
|
"call pnpm --filter @fusion/core test:embedded-postgres > `"$log`" 2>&1",
|
|
"exit /b %ERRORLEVEL%"
|
|
)
|
|
Write-Host "running embedded-PG smoke as $user..."
|
|
$sec = ConvertTo-SecureString $pass -AsPlainText -Force
|
|
$cred = New-Object System.Management.Automation.PSCredential("$env:COMPUTERNAME\$user", $sec)
|
|
$p = Start-Process -FilePath "cmd.exe" -ArgumentList '/c',$bat -Credential $cred -Wait -PassThru -WindowStyle Hidden
|
|
if (Test-Path $log) {
|
|
Write-Host "----- smoke.log (tail) -----"
|
|
Get-Content $log -Tail 200
|
|
} else {
|
|
Write-Host "smoke.log missing (bat may not have started)"
|
|
}
|
|
if ($p.ExitCode -ne 0) { Write-Error "embedded-PG smoke failed (exit $($p.ExitCode))"; exit 1 }
|
|
|
|
# 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 --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 --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 }
|
|
|
|
- name: Verify packaged app.asar assets
|
|
shell: pwsh
|
|
run: |
|
|
# FNXC:WindowsDesktopPackaging 2026-07-03-15:40:
|
|
# Field report Issue 5: the packaged desktop shipped without preload.js and
|
|
# dead-ended on "can't reach the Fusion backend" (preload absence is silent —
|
|
# the contextBridge never installs window.fusionShell/fusionAPI). scripts/build.ts
|
|
# verifies the pre-package staging tree; this asserts the SHIPPED app.asar itself
|
|
# contains the Electron main/preload/renderer entrypoints, since only the packed
|
|
# asar reflects what a user installs.
|
|
$required = @('dist/main.js', 'dist/preload.js', 'dist/client/index.html')
|
|
$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) {
|
|
$asar = Join-Path $root.FullName 'resources/app.asar'
|
|
if (!(Test-Path $asar)) { Write-Error "Missing packaged app.asar: $asar"; exit 1 }
|
|
$entries = npx --yes @electron/asar list $asar
|
|
if ($LASTEXITCODE -ne 0) { Write-Error "Failed to list app.asar: $asar"; exit 1 }
|
|
$normalized = $entries | ForEach-Object { $_.TrimStart('/','\').Replace('\','/') }
|
|
foreach ($asset in $required) {
|
|
if ($normalized -notcontains $asset) {
|
|
Write-Error "app.asar is missing required Electron asset '$asset' in $($root.Name); refusing to ship an incomplete package"
|
|
exit 1
|
|
}
|
|
}
|
|
Write-Host "$($root.Name)/resources/app.asar contains all required Electron assets"
|
|
}
|
|
|
|
# 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@v7
|
|
with:
|
|
name: fusion-desktop-windows
|
|
path: |
|
|
packages/desktop/dist-electron/*.exe
|
|
packages/desktop/dist-electron/*.blockmap
|