feat(squirrel-windows): inline installer logic; remove electron-winstaller dependency and its vendored binaries#9830
feat(squirrel-windows): inline installer logic; remove electron-winstaller dependency and its vendored binaries#9830mmaietta wants to merge 23 commits into
Conversation
…aller dependency and its vendored binaries
🦋 Changeset detectedLatest commit: 921b53f The changes in this PR will be included in the next version bump. This PR includes changesets to release 8 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
There was a problem hiding this comment.
Pull request overview
This PR migrates electron-builder-squirrel-windows off electron-winstaller by inlining the Windows Squirrel installer creation logic and removing the upstream dependency (and its vendored binaries) to address CVE/dependency-scanner findings, while keeping the existing packaging/signing flow within electron-builder.
Changes:
- Added a new
windowsInstaller.tsmodule that implements the required installer/nuspec generation helpers andcreateWindowsInstaller. - Updated
SquirrelWindowsTargetto use the new module, simplify vendor preparation, and adjust option computation/forwarding. - Updated the nuspec template and added Vitest unit coverage for the new helper functions; removed the
electron-winstallerdependency from relevant package manifests and lockfile.
Reviewed changes
Copilot reviewed 8 out of 10 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
packages/electron-builder-squirrel-windows/src/windowsInstaller.ts |
New inlined Squirrel.Windows installer implementation and helper utilities. |
packages/electron-builder-squirrel-windows/src/SquirrelWindowsTarget.ts |
Switch to the inlined installer module; simplify vendor setup and option computation. |
packages/electron-builder-squirrel-windows/template.nuspectemplate |
Replace loop-based template section with a prebuilt additionalFilesXml placeholder. |
packages/electron-builder-squirrel-windows/package.json |
Remove electron-winstaller and related type dependencies. |
test/src/windows/squirrelWindowsInstallerTest.ts |
New unit tests covering the new helper utilities. |
test/src/helpers/packTester.ts |
Import convertVersion from the new module instead of electron-winstaller. |
test/package.json |
Remove electron-winstaller dev dependency. |
pnpm-lock.yaml |
Lockfile cleanup reflecting removed dependencies. |
.changeset/remove-electron-winstaller-dep.md |
Changeset for the electron-builder-squirrel-windows minor bump. |
.gitignore |
Add ignore entry for Vitest smart cache file (now redundant with existing pattern). |
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…rate-electron-winstaller # Conflicts: # packages/electron-builder-squirrel-windows/src/SquirrelWindowsTarget.ts
…rate-electron-winstaller
Resolves conflicts by adopting the post-merge ESM conventions (import.meta, /internal barrel subpaths, dist/ output, packager getters without .info.) while keeping the inlined Squirrel installer (no electron-winstaller dep): - SquirrelWindowsTarget.ts: rewritten against new API surface; vendor from getSquirrelToolsetPath() bundle + runtime nuget/rcedit provisioning - toolset.ts: ESM imports; inlined env-dir validation (resolveEnvToolsetPath was removed upstream); added prepareNugetExe() runtime download - indexInternal.ts (app-builder-lib): export getRceditBundle - test.yaml: dropped temporary squirrel toolset CI scaffolding (replaced by runtime nuget download) - tests: import package src/ subpaths instead of out/ - pnpm-lock.yaml: reconciled (electron-winstaller removed) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…t + default spinner - BREAKING: remove squirrelWindows.customSquirrelVendorDir. The vendor toolset source is overridden via ELECTRON_BUILDER_SQUIRREL_TOOLSET_DIR (same nuget/rcedit provisioning). prepareSignedVendorDirectory collapses to one code path. - nuget download is offline/mirror-friendly: skips when a real (multi-MB) nuget.exe is already present (future bundle / pre-staged toolset), and is redirectable via ELECTRON_BUILDER_SQUIRREL_NUGET_URL (+ _SHA256). Adds a network-free skip test. - bundle install-spinner.gif and use it as the loadingGif fallback, restoring electron-winstaller parity (default fresh-install spinner). - regenerate scheme.json; changeset bumped to major with the breaking note. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…oval Add the v27 breaking-change entry for the removed customSquirrelVendorDir option (at-a-glance row + detail section) and a manual-step bullet in the v26→v27 guide, explaining the ELECTRON_BUILDER_SQUIRREL_TOOLSET_DIR replacement, its different directory layout, and the offline nuget options. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…nload Mark prepareNugetExe/isUsableNuget/NUGET_* for removal once squirrel.windows@1.1.1 (electron-builder-binaries#203) bundles the pinned nuget.exe; the skip-if-real-nuget logic already makes the runtime download a no-op against such a bundle. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…uirrel config
Replace the bespoke ELECTRON_BUILDER_SQUIRREL_TOOLSET_DIR / ELECTRON_BUILDER_SQUIRREL_NUGET_*
env vars with the standard ToolsetConfig pattern:
- add a `squirrel` field to ToolsetConfig ("1.1.0" | ToolsetCustom | "latest"), resolved
exactly like the other toolsets (version -> downloadBuilderToolset, object -> getCustomToolsetPath)
- export getCustomToolsetPath + resolveToolsetVersion from app-builder-lib/internal
- getSquirrelToolsetPath(toolset, resourcesDir) reads packager.config.toolsets.squirrel
- offline/custom bundles now use toolsets.squirrel (a ToolsetCustom whose vendor/ may ship a
real nuget.exe, which the skip-if-real check keeps); drop the nuget URL/SHA env overrides
- rewrite the toolset test (custom-dir resolution + invalid-url) ; keep the nuget skip test
- regenerate scheme.json; update v26->v27 + v27-breaking-changes docs
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…equested MSI - InstallerOptions uses `msi` (positive form) instead of `noMsi`; createWindowsInstaller passes --no-msi when !msi. Removes the redundant runtime noMsi deprecation shim (migrate-schema already rewrites the deprecated squirrelWindows.noMsi config to msi). - fixUpPaths: the Setup.msi rename only runs when MSI output was requested, so a missing Setup.msi is a real failure — throw an explicit error instead of swallowing it. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…squirrel Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…t win32 Squirrel-Mono.exe also shells out to rcedit.exe during --releasify (setPEVersionInfoAndIcon) to stamp version info + the app icon into Setup.exe, so the win32-only gate left rcedit.exe missing from the vendor dir on Linux/macOS, failing the build under mono/wine with "Failed to modify resources / ShellExecuteEx failed". electron-winstaller's vendor shipped a 32-bit rcedit.exe on all platforms; match that — use the 32-bit rcedit under wine (alongside the Win32 Squirrel vendor exes wine already runs), host-arch rcedit on Windows. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…uilds Squirrel's createMsiPackage (msi: true) runs candle.exe/light.exe from its vendor dir and reads template.wxs there; the squirrel.windows bundle ships neither, so MSI builds failed at pathToWixTools(). When msi is requested, download the shared WiX 3.11 toolset (wix-4.0.0.5512.2 — the same candle/light electron-builder's MSI target uses) and merge it into the vendor dir, and ship Squirrel's template.wxs in the package and copy it alongside. Gated on msi so non-MSI builds skip the ~4MB download. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…on missing Squirrel.exe - Select rcedit by host arch (x64 for x64/arm64, x86 only for ia32) instead of forcing 32-bit on non-Windows: the 32-bit build fails on arm64 macOS even under Rosetta (which translates x64, not x86). - Throw when Squirrel.exe is absent from the vendor dir instead of warn-and-skip: it always ships in the bundle, and skipping signing both produces a broken installer and bypasses the forceCodeSigning enforcement in signIf. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…4 namespace The shared wix-4.0.0.5512.2 toolset (the one electron-builder's MSI target uses) is a transitional WiX 4: its candle accepts the v3-style element structure but requires the v4 namespace, so Squirrel's WiX 3 template was rejected with CNDL0199. Swap template.wxs to http://wixtoolset.org/schemas/v4/wxs (dropping the unused util/netfx namespace decls — only the core <PropertyRef Id="NETFRAMEWORK45"> is used, supplied by candle's -ext WixNetFxExtension). Structure is unchanged, matching MsiTarget's template which compiles with the same toolset. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Closes #9077. This migration is driven by the need to workaround upstream CVE related to electron-winstaller's vendor directory. electron-builder uses an updated winCodeSign bundle from electron-builder-binaries that pulls directly from latest Windows Kits SDK.
Summary
electron-winstalleras a runtime dependency ofelectron-builder-squirrel-windowsand as a dev dependency of the test package, eliminating the vendored binaries (Squirrel.exe, nuget.exe, SyncReleases.exe, Squirrel-Mono.exe) that were flagged by dependency scanners.windowsInstaller.tsmodule, replacing the call tocreateWindowsInstallerfromelectron-winstaller. Logic is sourced fromelectron/windows-installer@main src/index.tsand trimmed to what electron-builder actually uses (usePackageJson: false, signing handled externally viapackager.signIf).prepareSignedVendorDirectorynow only downloads from our maintainedsquirrel.windows@1.0.0bundle, removing the parallel copy from theelectron-winstallernpm package's ownvendor/directory.os.arch→os.arch()bug inselect7zipArch— the bare property reference returned a function object instead of the arch string, silently breaking the7z-<arch>.exefilename construction on non-Windows cross-compile hosts.split/joinsubstitution. Thetemplate.nuspectemplate<% additionalFiles.forEach(...) %>loop is replaced by an<%- additionalFilesXml %>placeholder; the XML fragment is pre-built inbuildAdditionalFilesXml, preserving swiftshader/vk_swiftshader_icd.json support.remoteTokenconfig forwarding — user-configuredsquirrelWindows.remoteTokenis now included in the options object; previously it was silently dropped in favor of env vars only.packTester.tsto importconvertVersionfrom our module instead ofelectron-winstaller.Changed Files
packages/electron-builder-squirrel-windows/src/windowsInstaller.tsconvertVersion,escapeXml,renderNuspecTemplate,buildAdditionalFilesXml,createWindowsInstaller,InstallerOptionspackages/electron-builder-squirrel-windows/src/SquirrelWindowsTarget.ts./windowsInstaller; simplifiedprepareSignedVendorDirectory; simplifiedcomputeEffectiveDistOptions; fixos.arch()packages/electron-builder-squirrel-windows/template.nuspectemplateforEachblock with<%- additionalFilesXml %>packages/electron-builder-squirrel-windows/package.jsonelectron-winstaller,@types/archiver,@types/fs-extratest/package.jsonelectron-winstallerdev dependencytest/src/helpers/packTester.tsconvertVersionfromelectron-builder-squirrel-windows/out/windowsInstallertest/src/windows/squirrelWindowsInstallerTest.ts.changeset/remove-electron-winstaller-dep.mdelectron-builder-squirrel-windowsminor bumpDesign Notes
No new runtime dependencies. Lodash's
template()engine (an electron-winstaller transitive dep) is replaced bysplit/joinkey substitution. The nuspec template is now owned entirely by this package, with the one dynamic section (additionalFiles) handled by pre-building the XML inbuildAdditionalFilesXml.Mono/Wine execution unchanged. On Windows,
nuget.exe,SyncReleases.exe, andSquirrel.exeare called directly. On Linux/macOS,nuget.exeandSyncReleases.exerun undermono, andSquirrel-Mono.exereplacesSquirrel.exe— identical to the behavior of the removedelectron-winstaller.XML injection protection. All user-supplied metadata fields (name, title, version, authors, description, copyright, iconUrl, exe) pass through
escapeXmlbefore template substitution. TheadditionalFilesXmlfragment is constructed from hardcoded strings and is inserted verbatim.