chore(release): add the Windows x64 release path - #2182
Merged
Conversation
- Cover every Windows-only-observable input in the check workflow's paths: npm-spawn.mjs, the notices generator, .gitattributes, and the manifests had each already broken this path once without being able to trigger it. - Drop `verifyUpdateCodeSignature: false`. app-builder-lib only writes a publisher name when a certificate exists, and electron-updater skips the check when there is none, so the option is inert today and would silently suppress verification once signing is added. - Delete the `appDirectory` option: no caller in production or tests. - Narrow the runCommand comment to what the code does; deadlines are opt-in because codesign and notarization have no honest upper bound. - Assert the exact forbidden resource set instead of accepting any one match.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Maka has only ever shipped an Apple Silicon macOS build. 0.1.5 is meant to ship Windows x64 as well, so this adds the missing half of the release path and turns the single-platform workflow into a matrix.
apps/desktop/electron-builder.config.mjsgains awinsection: NSIS installer + ZIP for x64,Maka-${version}-win-${arch}.${ext}, andassets/icon.png(electron-builder converts it to.icothrough the same path macOS already uses).verifyUpdateCodeSignature: false, which electron-updater requires before it will install an unsigned update.scripts/package-windows-x64.mjsmirrors the macOS packaging script: fail-closed on anything but a Windows x64 host, assert the.exe,.zip, andlatest.yml, then dropwin-unpacked.scripts/verify-packaged-app.mjsis new and holds what the two verifiers share (command running, resource require/forbid lists, the node-pty probe, the filesystem-worker and renderer smokes, sha256).scripts/verify-macos-arm64-dmg.mjskeeps only its macOS-specific logic and imports the rest; its exported signatures are unchanged.scripts/verify-windows-x64.mjsverifies thewin-unpackeddirectory electron-builder just produced — the NSIS installer has no inspectable app structure, and the ZIP is an archive of exactly that directory — checking the x64 PE machine word, the product version, the resource require/forbid lists, and the packaged node-pty and renderer smokes, then writing.sha256for the installer and the ZIP. (macOS mounts its DMG instead because notarizing and stapling rewrite the DMG after packaging.)Release desktop(release-desktop.yml): abuildmatrix overmacos-15andwindows-2025with the Apple-only steps behindif: matrix.platform == 'macos', and a separatepublishjob that creates the one draft release from both platforms' artifacts. Splitting publish out is what keeps two parallel jobs from racing to create the same draft..github/RELEASE_CHECKLIST.mdgains a Windows acceptance section, including the expected SmartScreen warning andwingetfor ripgrep.Review rounds
An external review plus local verification turned up two defects in the first commit, both fixed in
20a2357:win.sign: falseis not a valid electron-builder option. The 26.8.1 schema setsadditionalProperties: false, sovalidateConfigurationrejected the whole config object — and since macOS and Windows share one config, this broke the existing macOS release too. Removed; unsigned is now expressed by configuring no certificate.appInfo.getVersionInWeirdWindowsForm), so0.1.5ships as0.1.5.0, and the verifier compared it strictly against the manifest's0.1.5. The unit test hid this by mocking the three-part string — a mock-shaped oracle. The verifier now compares the first three parts and requires a numeric build part, and the test pins the real four-part form.A second, fresh-context review of the combined branch then found a third blocker, fixed in
ab58cd9:spawn('npm')cannot resolve on Windows. libuv's process launcher tries only.comand.exeand ignoresPATHEXT, and npm on Windows isnpm.cmd— sopackage-windows-x64.mjswould have died with ENOENT on its first command, before any packaging happened. The macOS twin is unaffected because POSIXexecvpresolves the extensionless shim, which is exactly why the copy read as correct.runCommandnow goes through the shell on win32 only, and a test pins the spawn strategy on both platforms since the suite cannot run on Windows.All three were invisible to CI because nothing outside the release workflow ever loads that config or runs those scripts, and no CI job runs on Windows. Two seams closed:
scripts/electron-builder-config.test.mjsvalidates the config against electron-builder's own validator (with a negative case that reproduces thesignbug), andscripts/ci-test-plan.mjsnow routes the new release scripts, the sharedverify-packaged-app.mjs, and the release config to the lanes that cover them.Running it on Windows
Every defect below was found by
.github/workflows/release-windows-check.yml, added here: it runs the real packaging and verification onwindows-2025for any PR that touches this path. Before it existed, that path's first execution would have been release day, onmain, with a tag already reserved.It found five, in order:
spawn('npm')is unresolvable on Windows — libuv tries only.com/.exeand ignoresPATHEXT; npm isnpm.cmd. Died on the first command. The same rule then turned out to governnpm lsinsidecheck:release, so it lives inscripts/npm-spawn.mjsnow instead of being copied.check:third-party-noticesfailed on a checkout it had not touched — Git converts LF to CRLF in the working tree on Windows, and the check is a byte comparison..gitattributespins the tree to LF, which also keeps the shipped license text byte-identical between the two platforms' builds.Expand-Archiveneeded over 26 minutes on a packaged Electron app and never finished. Replacing the API barely helped, because the cost is writing tens of thousands of small files on Windows, not the PowerShell pipeline. The real fix was to stop rebuilding the object under test:win-unpackedis the app, and the ZIP is an archive of it. Verification went from >26min to 9s.maka-node-pty-okand then sat there until the deadline. It now exits explicitly once its output is flushed. The verifier also reports each stage and bounds every command, because a silent hang is worse than a failure — that is how this one was located at all.isBuiltinFilesystemWorkerSandboxAvailableis false on Windows, so the app never launches that worker and file tools run through the workspace executor. Driving it by hand only proved that a POSIX-only sandbox boundary rejects Windows paths — something no Windows user can reach. Removed.The end state passes: packaging 4m09s, verification 9s, including node-pty through conpty and a packaged renderer that mounts React and exposes the
window.makabridge.Verification
npm run format:check,npm run lint— clean.node --test scripts/electron-builder-config.test.mjs scripts/ci-test-plan.test.mjs scripts/macos-arm64-release.test.mjs scripts/windows-x64-release.test.mjs— 17/17 pass. The newscripts/windows-x64-release.test.mjscovers the host, input, architecture, and version fail-closed paths plus the unsigned-helper forbid list, and is wired intotest:scripts:extended.validateConfiguration— passing now, failing before the fix.Release desktop's macOS leg is still a first execution. It is unchanged in behavior — the extraction was diffed function by function againstmain.Rollout
Merge before dispatching the 0.1.5 release. #2180 carries the 0.1.5 version bump and CHANGELOG; the two are independent and can merge in either order.
Review focus
The unsigned Windows configuration and the publish-job split are the two decisions worth a second opinion.