windows-release
GitHub用于构建、验证并发布 Windows 桌面版 Electron 应用(NSIS 安装包及更新配置)至 GitHub Releases。涵盖版本管理、环境准备、构建流程、完整性校验及最终发布步骤,仅限 Windows 平台。
Trigger Scenarios
Install
npx skills add milind-soni/OpenMausBot --skill windows-release -g -y
SKILL.md
Frontmatter
{
"name": "windows-release",
"description": "Build, verify, and publish the Windows desktop build (NSIS installer + latest.yml) to the openmausbot-releases repo. Use when cutting a release, shipping a new version to Windows users, or when a Windows user reports they are stuck on an old version. Windows only — does not cover the macOS dmg\/notarization flow."
}
Windows release
Ships OpenMausBot-<version>-setup.exe and its update feed to
milind-soni/openmausbot-releases.
Scope: Windows only. The macOS build is a separate flow (dmg + notarytool + staple) that must run on a Mac. This skill never touches mac artifacts — but see Every release ships both before you finish.
Preconditions
- Run on Windows. NSIS packaging from macOS needs Wine; don't.
- Node 24+ (
package.jsonengines). Node 23 builds fine but pnpm warns on every step and CI runs 24 — don't debug a runtime oddity on the wrong major. - pnpm via
corepack pnpm. Ifcorepack enablefails with EPERM (no admin), drop apnpm.cmdshim containing@echo off/corepack pnpm %*somewhere on PATH —package:winchainspnpm build && …and needs barepnpmto resolve.
1. Version
Bump version in package.json. It must match the tag on the GitHub release you
upload to, and it becomes the version electron-updater compares against.
2. Build
pnpm install
pnpm typecheck
pnpm package:win
package:win deliberately omits build:speech — the dictation helper is a signed
macOS Swift binary and has no Windows counterpart.
Output in release/:
| File | Purpose |
|---|---|
OpenMausBot-<version>-setup.exe |
the installer |
latest.yml |
the update feed — see step 4 |
OpenMausBot-<version>-setup.exe.blockmap |
differential updates |
OpenMausBot-<version>-x64.zip |
portable, not used by the updater |
3. Verify before uploading
Three things silently produce a broken app if wrong. Check all three:
Test-Path release\win-unpacked\resources\server\index.js # harness server
Test-Path release\win-unpacked\resources\ui\index.html # built UI
Get-Content release\win-unpacked\resources\app-update.yml # feed config
- Missing
server/index.js→utilityProcess.forkfails → the 🐭 "Couldn't start the bot server" page. - Missing
ui/index.html→ server has nothing to serve → black window. app-update.ymlmust point atmilind-soni/openmausbot-releasesand, while the build is unsigned, must not containpublisherName— electron-updater would reject every update as untrusted.
Then smoke-test the installer itself. Run it, and confirm:
- It installs per-user with no UAC prompt and launches.
- The chat window renders (not the error page). Server logs land in
%APPDATA%\OpenMausBot\logs\server.log. - The model picker lists at least one provider — this exercises the
.cmd-shim resolution inserver/procs.ts, which only ever runs for real on Windows. - No update popup appears on launch. Background check failures are silent by design; a popup here means that regressed.
4. Publish
Upload to the same tag as the macOS release for that version, so one release carries both platforms.
Copy-Item release/OpenMausBot-<version>-setup.exe release/OpenMausBot-setup.exe
gh release upload v<version> --repo milind-soni/openmausbot-releases `
release/OpenMausBot-<version>-setup.exe `
release/OpenMausBot-setup.exe `
release/OpenMausBot-<version>-setup.exe.blockmap `
release/latest.yml
Both names are required, for different consumers:
OpenMausBot-<version>-setup.exeis whatlatest.ymlreferences by name and sha512. The auto-updater downloads exactly this.OpenMausBot-setup.exeis a byte-identical copy that gives the README's/releases/latest/download/OpenMausBot-setup.exebutton a stable URL. This mirrorsOpenMausBot.dmgsitting besideOpenMausBot-<version>.dmg.
latest.yml is not optional
Without it every installed Windows app 404s on check and stays on its version
forever. It is generated by package:win even under --publish never.
Never hand-edit it or carry one forward from a previous build. It pins the installer's sha512; a mismatch makes the updater download and then reject the update, which looks like "updates silently do nothing".
Every release ships both
A version that exists on macOS but not on this release is a Windows user stuck on
old code with no signal that anything is wrong — the updater reports "up to date"
because latest.yml still describes the older build.
So: whenever a new version goes out, this flow runs too. If Windows can't ship for some reason, don't publish the mac-only release under a new version tag either — or accept that Windows is knowingly frozen and say so in the release notes.
Because the two builds must run on two machines, the tag is the join point: cut the release, attach mac artifacts from the Mac, attach Windows artifacts from here.
Known: the build is unsigned
No certificate is configured, so SmartScreen shows "unknown publisher" and users
click More info → Run anyway. The README documents this. Auto-update still
works because it's unsigned (no publisherName to verify against).
If signing is added later, it goes under win.signtoolOptions or
win.azureSignOptions in electron-builder.yml — electron-builder 26 nests these;
there is no top-level win.certificateFile. Once signed, keep the certificate
subject stable forever, or list both old and new in publisherName; changing it
strands every already-installed user.
Version History
- 6b099e3 Current 2026-08-16 15:44


