Releases & updates¶
The current release is 2026.10.10, the first release cut from a v* tag
(the earlier releases were produced by a manual workflow_dispatch). Each
release ships the Windows, Linux and macOS artifacts, their update manifests and
a *.sha256 checksum for every artifact. See
Roadmap for what is still outstanding (the updater upgrade proof).
How users get updates¶
The desktop app embeds electron-updater and checks the project's GitHub
Releases for a newer version:
- on startup (a few seconds after launch), and
- on demand via
Help ▸ Check for Updates....
When an update is available it downloads in the background (progress is reported), and once complete the app prompts to Restart and install. Updates require a stable internet connection and a published release that contains the update manifest.
Windows installer constraint
Updates apply only when the app was installed into the default directory — hence the installer does not allow a custom install location.
Versioning¶
Release versions are date-based (YYYY.M.D, e.g. 2026.9.19, which sorts
as a valid semver and is always greater than the previous release).
The repository itself stays at 0.0.0 — the version is generated and
injected at build time, never committed:
scripts/set-build-version.mjscomputes the version from the current UTC date (or takes an explicitVERSION), validatesYYYY.M.D, and writes it into a givenpackage.json.- Local packaging (
yarn package:win,package:linux,package:mac) runsscripts/package-electron.mjs: it injects the build version into a staging copy ofapplications/electron/package.json, packages with electron-builder, and restores the checked-in file, so the Git working tree is never left dirty. - CI reads the version from the release tag (
vYYYY.M.D→YYYY.M.D) and injects it into the disposable checkout before packaging.
There is no version-bump script and no version-bump commit to make.
Releasing a new version¶
- The version comes from the tag name, so there is nothing to bump or commit. Push the tag:
git tag v2026.9.19
git push origin v2026.9.19
(A manual run via workflow_dispatch without a tag uses the version
input, or today's UTC date if no input is given.)
-
.github/workflows/release.ymlruns in three phases: -
prepare — computes the version (from the tag) and creates a draft GitHub Release for the tag.
-
build & publish — on three runners in parallel, each uploading its artifacts plus the update manifest (
latest.yml,latest-mac.ymlorlatest-linux.yml) into the draft release (--publish always,GH_TOKEN=GITHUB_TOKEN):windows-2022→--win(NSIS + portable)ubuntu-22.04→--linux(AppImage + rpm + deb)macos-15→--mac(dmg + zip), unsigned unless the Apple signing secrets are configured (see macOS signing & notarization).
-
finalize — publishes the draft release as soon as all three build jobs succeed.
The draft is created up front so the parallel jobs never race to create the release, and it is published automatically at the end; no manual step is required.
- Installed apps on the previous version are then offered the update (only if the new version is greater, semver-wise). Note: electron-updater only resolves published releases, never drafts — which is why the workflow publishes at the end.
Release workflow details¶
- Trigger:
pushof tags matchingv[0-9]*, or manualworkflow_dispatchwith aversioninput. - Permissions:
contents: write(create release + upload assets). - Draft release is created once by the
preparejob withgh release create --draft; the build jobs only ever upload into it. - Native rebuild step excludes
node-ptyto avoid the MSB8040 Spectre failure (it uses N-API prebuilds compatible with Electron anyway). yarn package:win / package:linux / package:macexist for local testing but always use--publish never; only CI publishes.- Every artifact also gets a SHA-256 checksum (
*.sha256), uploaded beside the installer to the release and as a workflow attachment.
macOS signing & notarization¶
macOS builds are unsigned by default — the project has no Apple Developer ID credentials. Enabling signing/notarization is configuration-only, no workflow code changes are required.
Add these repository Secrets (Settings ▸ Secrets and variables ▸ Actions):
| Secret | Value |
|---|---|
CSC_LINK |
Base64-encoded Developer ID Application .p12 (export from Keychain: right-click certificate → Export… → <cert>.p12, then base64 -i com.your.id.p12). |
CSC_KEY_PASSWORD |
The <cert>.p12 password. |
APPLE_ID |
Your Apple Developer account email. |
APPLE_APP_SPECIFIC_PASSWORD |
An app-specific password generated under Apple ID ▸ Sign-In & Security. |
APPLE_TEAM_ID |
Your Developer team ID (Apple Developer portal, Membership). |
CI then behaves as follows:
CSC_IDENTITY_AUTO_DISCOVERYistrueon the macOS job exactly whenCSC_LINKis set, andfalseotherwise (Windows/Linux stay unsigned).- With
CSC_LINKset, electron-builder signs the app with the Developer ID certificate. - With
APPLE_ID+APPLE_APP_SPECIFIC_PASSWORD+APPLE_TEAM_IDset, electron-builder additionally notarizes and staples the artifacts (mac.notarize: true). - The workflow's macOS verification step then hard-asserts
codesign --verify --deep --strictand Gatekeeperspctl -a -vvin addition to the plist/DMG checks it always runs.
The hardened runtime and entitlements are already configured and the signing assertions activate automatically — nothing else to change in the repo.
Until signing is enabled, the release notes carry a Gatekeeper warning
automatically: the prepare job prepends what macOS will say about the
unsigned build ("cannot be opened because the developer cannot be verified" /
"is damaged") and the two ways past it (right-click → Open, or
xattr -dr com.apple.quarantine). The warning disappears by itself the moment
the CSC_LINK secret is populated, so the notes cannot go stale.
Update manifests¶
electron-builder writes the per-platform update manifest only during a
publish build:
| Manifest | Serves |
|---|---|
latest.yml |
Windows NSIS *exe delta/full updates |
latest-mac.yml |
macOS zip updates |
latest-linux.yml |
Linux AppImage/deb/rpm updates |
These files (plus .blockmap files and the installers) are uploaded to the
release by the corresponding matrix job. The app discovers them through the
GitHub provider configured in electron-builder.yml.
Verifying the updater¶
An installed build only ever sees a published release, and only one with a greater version, so an end-to-end check needs a newer release to be published before it starts.
Verified against the published releases (not yet an installed upgrade — see Roadmap):
v2026.10.10is the latest published release (GET /repos/mrhunsaker/notepadia-theia/releases/latestreturns it, not a draft), and2026.10.10sorts greater than2026.10.9.- All three manifests download from it and are internally consistent:
latest.yml,latest-linux.ymlandlatest-mac.ymleach carryversion: 2026.10.10, afiles[]entry per target with itssha512andsize, and a matching top-levelpath/sha512.
Still to demonstrate on real hardware, and the only remaining part of this milestone:
- Install the previous build (
v2026.10.9) on Windows and on Linux and launch it. Help ▸ Check for Updates..., confirm the download and the restart prompt, and confirm the app relaunches at2026.10.10.
Record the exact versions tested here once that run is done.