-
-
Notifications
You must be signed in to change notification settings - Fork 5
Maintainer Releasing
How updates flow through Minnow — releasing a new version (for maintainers) and
receiving one (for users). Auto-update is built on
electron-updater against GitHub Releases
(henrigrimm/minnow). Implementation: electron/updater.ts +
electron/updater-core.ts; UI in
src/ui/settings-updates.ts and
src/os/update-menubar.ts. Tracked in
MIN-384.
Platform support today: Windows (NSIS), Linux (AppImage), and signed macOS (Developer ID + notarization). Unsigned macOS installs show a disabled updater with a signing note. On Windows/macOS hosts, build Linux with
npm run package:linux:docker(Docker). Dev and browser sessions can't self-update and show a hint instead of controls.
Local packaging never uploads anything (electron-builder runs with --publish never); you
create a manually versioned GitHub release by hand. The build.publish config in
package.json exists only so packaging emits the latest.yml feed
file. Four steps:
Edit version in package.json:
This is mandatory for every release. An installed app decides whether to update by
comparing its own version against the one in latest.yml. If you don't bump, nobody
upgrades. Use semver: patch for fixes, minor for features.
npm run packageThis runs build → electron:build → electron-builder and writes to release/pkg/:
| File | Role |
|---|---|
Minnow-Setup-<version>.exe |
The NSIS installer users download (Windows). |
latest.yml |
Windows update feed. Version + SHA512 hashes; electron-updater fetches this to detect a new build. |
Minnow-Setup-<version>.exe.blockmap |
Enables smaller delta downloads between versions. |
Minnow-<version>-x86_64.AppImage |
Linux portable install (npm run package:linux or package:linux:docker on Windows/macOS). |
latest-linux.yml |
Linux update feed — attach alongside the AppImage. |
On https://github.com/henrigrimm/minnow/releases → Draft a new release:
-
Tag:
v<version>(e.g.v1.0.1), created against the commit you packaged from. -
Attach platform artifacts from
release/pkg/(Windows) andrelease/pkg-linux/when you built Linux via Docker. At minimum per platform: installer/binary + matching feed (latest.ymlon Windows,latest-linux.ymlon Linux) +.blockmapwhere electron-builder emits one. Without the feed file, installed apps never see the release. -
The feed and the installer must be from the same build.
electron-updaterhashes the downloaded.exe/ AppImage / zip againstsha512+sizein the YAML. Replacing an installer on an existing tag without replacing that platform’slatest*.ymllooks like “it downloaded but will not install.” After attaching assets, runnode scripts/verify-github-update-feed.mjs. -
Publish the release (do not leave it as a draft). Draft releases are invisible to
electron-updater; Settings will show Could not check for updates until the release is published. - Release notes / body: this text is what users see under "What's new" in Settings and in the menubar popover. Write it for users, not as a changelog dump.
The pre-release checkbox on the GitHub release is the channel switch:
| GitHub setting | Who receives it |
|---|---|
| Latest release (pre-release unchecked) | Everyone on the Stable channel. |
| Pre-release (checkbox checked) | Only users who selected the Beta channel. |
Beta rides GitHub pre-releases via autoUpdater.allowPrerelease — there's no separate
beta feed to maintain.
beta nightly release runs every day at
03:30 UTC (and can be run manually). It packages Windows, Linux, and Apple Silicon macOS
from main. It uses the package version when it is ahead of the latest stable tag;
otherwise it advances to the next patch, then appends a unique
-beta.YYYYMMDD.RUN.ATTEMPT suffix, and publishes it as a GitHub
pre-release only after every installer and update feed has uploaded. Users on the Beta
channel receive it through the existing updater; Stable users do not.
Before enabling its macOS job, add these repository Actions secrets:
| Secret | Value |
|---|---|
MACOS_CERTIFICATE_P12_BASE64 |
Base64-encoded Developer ID Application .p12 certificate. |
MACOS_CERTIFICATE_PASSWORD |
Password for that .p12. |
APPLE_ID |
Apple ID used for notarization. |
APPLE_APP_SPECIFIC_PASSWORD |
Apple app-specific password. |
APPLE_TEAM_ID |
Apple Developer team ID. |
The macOS job intentionally fails when these are absent: unsigned macOS builds disable the in-app updater and are not suitable for the beta release channel.
[ ] Bumped version in package.json (and committed)
[ ] npm run package:win (and package:linux or package:linux:docker) succeeded
[ ] release/pkg/ has .exe + latest.yml + .blockmap; Linux AppImage + latest-linux.yml if shipping Linux
[ ] GitHub release tagged v<version>
[ ] All platform feed files and installers attached
[ ] Release notes written for users
[ ] Pre-release flag set correctly (unchecked = Stable, checked = Beta)
Builds are unsigned, so the first manual install of the .exe may trigger a
SmartScreen warning ("More info → Run anyway"). Auto-updates after that first install are
silent — the user doesn't re-clear SmartScreen on every update.
Automatic and calm by design. On a packaged Windows install:
-
Check. 15 seconds after launch, then every 4 hours, the app fetches
latest.ymland compares versions. Launch is never blocked on this. - Download. A newer version downloads in the background automatically — no prompt, no interruption.
- Install on your terms. Click Restart to update when you're ready. If you never do, the update installs automatically the next time you quit Minnow normally.
Menubar pill (left of the settings gear) — silent unless there's something to act on:
| State | Pill |
|---|---|
| Up to date | Hidden — zero noise. |
| Downloading | ↓ 67% |
| Ready | Accent Restart · 1.0.1 — click for a popover with release notes, Restart now / Later, and a link to Settings. |
Settings → General → App updates — the full picture and all manual controls:
- Status strip: up to date / checking / downloading % / ready / couldn't check.
- Installed version, Last checked, Next automatic check.
- Update channel: Stable / Beta toggle.
- Check for updates button (manual check).
- Restart to update button (appears when a build is ready).
- What's new expander with the release notes.
Toggle Stable ↔ Beta in Settings → General → App updates. No reinstall — the choice
persists to ~/.minnow/updater.json and triggers an immediate re-check. Beta simply opts
you into GitHub pre-releases, which may be less stable; switch back anytime.
Deliberately quiet:
- Background check fails (offline, GitHub unreachable) → silent, logged, retried next cycle. No toasts.
- You click "Check for updates" and it fails → an inline error in the status strip (the only place failures surface, since you asked).
- A download is interrupted → retried on the next cycle; a build that already finished downloading stays "ready" and is never lost to a later failed check.
The complete "old install upgrades itself" path can only be exercised once two versions exist on GitHub Releases. The practical first validation:
- Release
1.0.1, install it. - Release
1.0.2. - Launch the
1.0.1install and confirm it detects1.0.2, downloads, shows the menubar pill, and installs on restart.
Unit coverage for the state machine and UI lives in
test/electron/updater-core.test.mts,
test/settings/settings-updates.test.mts,
and test/os/update-menubar.test.mts.
| Concern | Where |
|---|---|
| Updater controller (schedule, download, install) | electron/updater.ts |
| State machine (pure, testable) | electron/updater-core.ts |
IPC channels (minnow:updater:*) |
electron/ipc-channels.ts |
| Renderer bridge + display helpers | src/electron/updater-client.ts |
| Settings UI | src/ui/settings-updates.ts |
| Menubar pill + popover | src/os/update-menubar.ts |
| Persisted channel choice | ~/.minnow/updater.json |
Publish config (--publish never locally) |
package.json build.publish + scripts/electron-builder-run.mjs
|
| Packaging targets, extra resources, asar unpack |
package.json build + context.md
|
| macOS signing & notarization | macos-signing.md |
Generated from documentation/. Do not edit generated pages directly.
Extensions
Developer reference
Contributing
- Accessibility and keyboard-first audit
- Minnow apps
- Architecture overview
- Command reference
- LAN companion
- Orchestrator V2 board testing
- Contributing to Minnow
- Setup from source
Design system
- CSS file map
- Layout shell
- UI primitives
- Minnow design system (current state)
- Minnow Shell
- Themes
- Design tokens
Guides
- Accessibility and keyboard-first audit
- Minnow apps
- Architecture overview
- Command reference
- Configuration & storage
- Keyboard shortcuts
- LAN companion
- Model bench: Flip Match v1
- Orchestrate board testing
- Minnow guides
- Release E2E testing guide
- Setup guide
- Troubleshooting
- Minnow wiki
Maintainers
- macOS release signing & notarization
- Prompt ownership matrix (MIN-379)
- Releasing Minnow
- Settings reference
- GitHub Wiki publishing
Apps
Chat
Core concepts
Extend Minnow
Get started
Orchestrate
Overview
Reference
{ "version": "1.0.1" // was 1.0.0 }