Files
fusion/.github/workflows/desktop-windows.yml
dependabot[bot] 74d6513fae chore(deps): bump actions/upload-artifact from 4 to 7 (#2444)
Bumps
[actions/upload-artifact](https://github.com/actions/upload-artifact)
from 4 to 7.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/actions/upload-artifact/releases">actions/upload-artifact's
releases</a>.</em></p>
<blockquote>
<h2>v7.0.0</h2>
<h2>v7 What's new</h2>
<h3>Direct Uploads</h3>
<p>Adds support for uploading single files directly (unzipped). Callers
can set the new <code>archive</code> parameter to <code>false</code> to
skip zipping the file during upload. Right now, we only support single
files. The action will fail if the glob passed resolves to multiple
files. The <code>name</code> parameter is also ignored with this
setting. Instead, the name of the artifact will be the name of the
uploaded file.</p>
<h3>ESM</h3>
<p>To support new versions of the <code>@actions/*</code> packages,
we've upgraded the package to ESM.</p>
<h2>What's Changed</h2>
<ul>
<li>Add proxy integration test by <a
href="https://github.com/Link"><code>@​Link</code></a>- in <a
href="https://redirect.github.com/actions/upload-artifact/pull/754">actions/upload-artifact#754</a></li>
<li>Upgrade the module to ESM and bump dependencies by <a
href="https://github.com/danwkennedy"><code>@​danwkennedy</code></a> in
<a
href="https://redirect.github.com/actions/upload-artifact/pull/762">actions/upload-artifact#762</a></li>
<li>Support direct file uploads by <a
href="https://github.com/danwkennedy"><code>@​danwkennedy</code></a> in
<a
href="https://redirect.github.com/actions/upload-artifact/pull/764">actions/upload-artifact#764</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/Link"><code>@​Link</code></a>- made
their first contribution in <a
href="https://redirect.github.com/actions/upload-artifact/pull/754">actions/upload-artifact#754</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/upload-artifact/compare/v6...v7.0.0">https://github.com/actions/upload-artifact/compare/v6...v7.0.0</a></p>
<h2>v6.0.0</h2>
<h2>v6 - What's new</h2>
<blockquote>
<p>[!IMPORTANT]
actions/upload-artifact@v6 now runs on Node.js 24 (<code>runs.using:
node24</code>) and requires a minimum Actions Runner version of 2.327.1.
If you are using self-hosted runners, ensure they are updated before
upgrading.</p>
</blockquote>
<h3>Node.js 24</h3>
<p>This release updates the runtime to Node.js 24. v5 had preliminary
support for Node.js 24, however this action was by default still running
on Node.js 20. Now this action by default will run on Node.js 24.</p>
<h2>What's Changed</h2>
<ul>
<li>Upload Artifact Node 24 support by <a
href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a> in <a
href="https://redirect.github.com/actions/upload-artifact/pull/719">actions/upload-artifact#719</a></li>
<li>fix: update <code>@​actions/artifact</code> for Node.js 24 punycode
deprecation by <a
href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a> in <a
href="https://redirect.github.com/actions/upload-artifact/pull/744">actions/upload-artifact#744</a></li>
<li>prepare release v6.0.0 for Node.js 24 support by <a
href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a> in <a
href="https://redirect.github.com/actions/upload-artifact/pull/745">actions/upload-artifact#745</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/upload-artifact/compare/v5.0.0...v6.0.0">https://github.com/actions/upload-artifact/compare/v5.0.0...v6.0.0</a></p>
<h2>v5.0.0</h2>
<h2>What's Changed</h2>
<p><strong>BREAKING CHANGE:</strong> this update supports Node
<code>v24.x</code>. This is not a breaking change per-se but we're
treating it as such.</p>
<ul>
<li>Update README.md by <a
href="https://github.com/GhadimiR"><code>@​GhadimiR</code></a> in <a
href="https://redirect.github.com/actions/upload-artifact/pull/681">actions/upload-artifact#681</a></li>
<li>Update README.md by <a
href="https://github.com/nebuk89"><code>@​nebuk89</code></a> in <a
href="https://redirect.github.com/actions/upload-artifact/pull/712">actions/upload-artifact#712</a></li>
<li>Readme: spell out the first use of GHES by <a
href="https://github.com/danwkennedy"><code>@​danwkennedy</code></a> in
<a
href="https://redirect.github.com/actions/upload-artifact/pull/727">actions/upload-artifact#727</a></li>
<li>Update GHES guidance to include reference to Node 20 version by <a
href="https://github.com/patrikpolyak"><code>@​patrikpolyak</code></a>
in <a
href="https://redirect.github.com/actions/upload-artifact/pull/725">actions/upload-artifact#725</a></li>
<li>Bump <code>@actions/artifact</code> to <code>v4.0.0</code></li>
<li>Prepare <code>v5.0.0</code> by <a
href="https://github.com/danwkennedy"><code>@​danwkennedy</code></a> in
<a
href="https://redirect.github.com/actions/upload-artifact/pull/734">actions/upload-artifact#734</a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="043fb46d1a"><code>043fb46</code></a>
Merge pull request <a
href="https://redirect.github.com/actions/upload-artifact/issues/797">#797</a>
from actions/yacaovsnc/update-dependency</li>
<li><a
href="634250c138"><code>634250c</code></a>
Include changes in typespec/ts-http-runtime 0.3.5</li>
<li><a
href="e454baaac2"><code>e454baa</code></a>
Readme: bump all the example versions to v7 (<a
href="https://redirect.github.com/actions/upload-artifact/issues/796">#796</a>)</li>
<li><a
href="74fad66b98"><code>74fad66</code></a>
Update the readme with direct upload details (<a
href="https://redirect.github.com/actions/upload-artifact/issues/795">#795</a>)</li>
<li><a
href="bbbca2ddaa"><code>bbbca2d</code></a>
Support direct file uploads (<a
href="https://redirect.github.com/actions/upload-artifact/issues/764">#764</a>)</li>
<li><a
href="589182c5a4"><code>589182c</code></a>
Upgrade the module to ESM and bump dependencies (<a
href="https://redirect.github.com/actions/upload-artifact/issues/762">#762</a>)</li>
<li><a
href="47309c993a"><code>47309c9</code></a>
Merge pull request <a
href="https://redirect.github.com/actions/upload-artifact/issues/754">#754</a>
from actions/Link-/add-proxy-integration-tests</li>
<li><a
href="02a8460834"><code>02a8460</code></a>
Add proxy integration test</li>
<li><a
href="b7c566a772"><code>b7c566a</code></a>
Merge pull request <a
href="https://redirect.github.com/actions/upload-artifact/issues/745">#745</a>
from actions/upload-artifact-v6-release</li>
<li><a
href="e516bc8500"><code>e516bc8</code></a>
docs: correct description of Node.js 24 support in README</li>
<li>Additional commits viewable in <a
href="https://github.com/actions/upload-artifact/compare/v4...v7">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/upload-artifact&package-manager=github_actions&previous-version=4&new-version=7)](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>
2026-07-27 19:06:09 -07:00

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@v4
- 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