v1.3.0 - Self-Updating
🚀 notihub v1.3.0
Release Title: v1.3.0 - Self-Updating
🌟 Highlights
- ⬇️ notihub updates itself. An available update is now a Download & Install button instead of a link to this page. It fetches the release zip, checks it against the SHA-256 GitHub publishes for that exact asset, and replaces the installed app — you restart when it suits you.
- 🔓 No more "notihub is damaged" on updates.
com.apple.quarantineis applied by browsers, so a build notihub downloads for itself is never quarantined. Thexattrcommand is now only ever needed for the first manual install. - 🍺 Works the same however you installed. The Homebrew cask declares
auto_updates, sobrew upgradesteps aside instead of fighting the app over versions. - 🐛 Fixes a broken v1.2.0 npm package — see below. If you installed the CLI from npm, please upgrade.
🛠️ Detailed Changelog
⬇️ In-place updates without Squirrel.Mac
Squirrel.Mac is macOS's usual update mechanism and it is unavailable to this project: it installs only an update signed by the same Apple Developer ID as the running copy, which ad-hoc signing (no paid Developer ID) cannot provide. Rather than leave updates manual, src/updater.js does by hand exactly what a user was doing:
- Download
notihub-v<version>-mac.zipfrom the release. - Verify it against the
digestGitHub publishes per asset. A mismatch deletes the download before anything is unpacked — nothing is installed that does not hash to the published value. - Unpack with
ditto(framework symlinks survive;cpwould flatten them). - Confirm the unpacked build passes
codesignand reports the version the release advertised. - Move the installed bundle aside, copy the new one in, and restore the old one if the copy fails.
If notihub cannot write over its own bundle — a non-admin account, or a copy running from somewhere read-only — the button falls back to opening the release page, exactly as before.
🐛 The npm package published for v1.2.0 was broken
npm rejected the bare name notihub as too similar to an existing package, so v1.2.0 was published scoped, as @thuong180702/notihub. Two places derived the app name from the package name, and so began looking for /Applications/@thuong180702/notihub.app:
bin/notihub.js— the CLI stopped finding the installed app, silently demotingnotihub,notihub notifyandnotihub doctorto an unpackaged Electron run, which macOS refuses to deliver notifications from. Anyone who installed@thuong180702/notihub@1.2.0from npm should upgrade.scripts/build-app.js— building from source failed outright.
Both now read a new productName field, which is the app's name and is independent of whatever the registry requires the package to be called.
🔁 Downloads retry
A dropped connection partway through the ~120MB transfer (seen as net::ERR_CONNECTION_RESET while testing this) used to cost the whole update. Downloads now retry before surfacing a failure.
🧷 Restarting into the new build
notihub holds a single-instance lock, so a new copy that starts before the old process has exited sees the lock and quits — which would look like the update killed the app. The restart now waits for the old process to exit, then goes through open -a so LaunchServices gives the new copy its menu bar slot and notification identity.
✅ How this was verified
The full chain was run against the live v1.2.0 release under real Electron — download, checksum reject and accept, extract, version-mismatch reject, swap, codesign, launch, and cleanup: 19 checks, alongside 16 new unit tests.
Two bugs were caught by that testing rather than by review:
- Deriving the bundle path from the executable returned
Electron.appon a dev run (that binary also sits three levels inside a.app) — an updater willing to write there would have overwrittennode_modules. It now requires its own bundle name. - The single-instance lock race described above.
📦 Download Assets & Checksums
| Asset File | Format | SHA-256 Checksum |
|---|---|---|
notihub-v1.3.0-mac.dmg |
Native macOS DMG Installer | 50bef908d980334ff8c35a89ada3eebf1db8cdce6d644716341e5481e447aa87 |
notihub-v1.3.0-mac.zip |
Portable Zip Archive | 64e7a0e28734274ffd9d0267548b2ebd4f5a782c08ade838aefaf6f11c61584a |
📥 Installation Options
Method 1: Homebrew (Recommended)
brew tap thuong180702/notihub
brew install --cask notihubMethod 2: npm (CLI companion)
npm install -g @thuong180702/notihubMethod 3: DMG Installer
- Download
notihub-v1.3.0-mac.dmgbelow. - Double click to open the DMG, then drag
notihub.appintoApplications.
Method 4: Direct Zip Download
- Download
notihub-v1.3.0-mac.zip. - Unzip and move
notihub.appinto/Applications.
⬆️ Upgrading from v1.2.0 or earlier
This is the last update you have to install by hand — v1.3.0 onwards, notihub offers to do it for you.
Replace the app as usual. No bundle identifier change, so notifications stay granted.
⚠️ Gatekeeper Notice
notihub is signed ad-hoc, not notarized by Apple, so macOS will refuse this manual install with "notihub is damaged and can't be opened". This isn't corruption — it's Gatekeeper rejecting an unnotarized app. Clear the quarantine flag once:
xattr -dr com.apple.quarantine /Applications/notihub.appUpdates notihub installs itself are never quarantined, so this is the last time you should need it.