الصفحات · Mark It Down
Auto-Update
Status: shipped in Phase 0.14 · Issue: #28
Both shipping surfaces — the VSCode extension and the standalone Electron app — now stay current via GitHub Releases. One source of truth, no extra hosting.
At a glance
| Surface | Channel | What runs |
|---|---|---|
| VSCode extension (Marketplace) | vscode.marketplace | VSCode's native auto-update — silent, on by default |
| VSCode extension (.vsix) | GET /repos/fadymondy/mark-it-down/releases/latest | In-extension poller checks once per launch + every 6h; surfaces a notification with Open Release / View Changes actions |
| Electron app | electron-updater (GitHub provider) | App checks on launch, downloads in background, prompts user to install on next quit (or restart now) |
VSCode side
Two paths users can be on:
Marketplace install
The extension is published to the VSCode Marketplace as fadymondy.mark-it-down. VSCode polls the Marketplace and pulls updates automatically — nothing extension-side to do. Whatever VSCode's update settings say is what happens.
Self-installed .vsix
For users who downloaded the .vsix from a GitHub Release (or sideloaded from a build), there's no Marketplace channel. The extension polls GitHub itself:
Behavior notes:
- Never auto-installs. Pulling executable code from a remote without a user gesture is a security smell. The notification is the action.
- Doesn't re-notify for the same version unless the user clicks
Laterthen quits + relaunches. Tracked viaglobalState[markItDown.updates.lastSeenVersion]. View Changesopens an untitled markdown buffer with the release body so the user can read offline / save / share.- Manual check:
Mark It Down: Check for Updatesfrom the command palette runs the same check on demand and surfaces "you're on the latest" if there's nothing new (the auto-poll stays silent in that case). - What's New on first launch after update: when the installed version differs from
globalState[markItDown.updates.installedVersion], the extension shows a one-time "Mark It Down updated to v0.X.Y" toast with aView What's Newaction that opens the GitHub release page. First-ever install is silent (nolastvalue to compare against).
Settings:
| Setting | Default | What it does |
|---|---|---|
markItDown.updates.checkOnLaunch | true | Poll GitHub on launch + every 6h. Set to false to disable; Check for Updates command still works manually. |
markItDown.updates.channel | "stable" | "stable" follows releases/latest (skips pre-releases). "beta" opts into pre-release tags (e.g. v0.3.0-rc.1). For the Electron app, set MID_CHANNEL=beta env var. See Pre-release / beta channel below. |
Pre-release / beta channel
Cut a tag like v0.3.0-rc.1 or v0.3.0-beta.2. The release workflow:
- Builds Electron installers +
.vsixas for any release - Sets the GitHub release's
prerelease: trueflag (because the tag has a-in it)
The two pollers behave differently per channel:
- Stable channel (default): the in-extension poller hits
/repos/.../releases/latestwhich GitHub itself filters to skip pre-releases — beta tags are invisible.electron-updater's default channel =latestdoes the same. - Beta channel (
markItDown.updates.channel: "beta"/MID_CHANNEL=beta): the in-extension poller hits/repos/.../releases?per_page=20and picks the newest non-draft (pre-release OR stable).electron-updater.allowPrerelease = truedoes the same on the Electron side.
So beta users see v0.3.0-rc.1 immediately; stable users wait until you cut v0.3.0 proper.
Electron side
Wired via electron-updater (the official update channel for electron-builder). The package.json#build.publish block:
electron-builder writes a latest-mac.yml / latest.yml / latest-linux.yml next to each installer at release time, and electron-updater fetches whichever matches the running platform.
Lifecycle in the Electron app
User chooses on the post-download dialog:
- Restart and install now —
quitAndInstall(true, true)runs the installer immediately - Install on next launch —
autoInstallOnAppQuit = trueis set, the install runs the next time the user quits
Settings (defaults):
autoDownload = true— downloads happen in the background, no consent dialog before the bytes startautoInstallOnAppQuit = false— explicit user opt-in required for silent installs (this is the conservative choice)
A Help → Check for Updates… menu item lets users force a check and surfaces "You're on the latest" if nothing's available.
Code signing
For macOS auto-updates to work, the DMG must be signed AND notarized. An unsigned DMG installs fine on first download, but electron-updater refuses to apply updates to it (Apple's Gatekeeper rejects the differential update).
The release workflow's env block already references the right secrets:
Add the 5 secrets in the repo's Settings → Secrets and variables → Actions following the step-by-step in docs/releasing.md → Setting up macOS code signing.
Without those secrets, builds still succeed and Linux/Windows updates work fine. macOS users on unsigned builds will see "you're on the latest" indefinitely from electron-updater's perspective.
Release flow (shared)
A push of a tag matching v*.*.* triggers .github/workflows/release.yml:
So one tag push produces:
Mark.It.Down-0.2.0-arm64.dmg,Mark.It.Down-0.2.0-x64.dmg(macOS)Mark.It.Down.Setup.0.2.0.exe(Windows)Mark.It.Down-0.2.0.AppImage,mark-it-down_0.2.0_amd64.deb(Linux)latest-mac.yml,latest.yml,latest-linux.yml(electron-updater metadata)mark-it-down-0.2.0.vsix(the VSCode extension)- A release body sourced verbatim from
CHANGELOG.md's## [0.2.0]section
See docs/releasing.md for the manual checklist that wraps a release.
Edge cases
- Pre-release tags (e.g.
v0.3.0-rc.1) — the GitHubreleases/latestendpoint skips releases markedprerelease: true, so the in-extension poller won't notify on them.electron-updaterhonors the same default. To roll a pre-release channel, mark the GitHub release as "Pre-release"; users opted in viaautoUpdater.channel = 'beta'(not wired in v0.14) would receive it. - Network failures — both checkers swallow errors silently. The user only sees a failure when they manually invoked
Check for Updates. - Rate limiting — unauthenticated GitHub API calls cap at 60/hour per IP. The 6-hour poll interval keeps us well under that even with multiple VSCode windows open.
- Same version, different build — semver comparison is exact (
0.1.0 == 0.1.0→ no notification). If you re-tag the same version, users won't be re-pinged — bump the patch number. - Extension installed to extra-mode VSCode forks (Cursor, Code-OSS, etc.) — they don't all hit the Marketplace, so the in-extension poller is the active path there too.
Files of interest
- src/updates/updateChecker.ts — VSCode-side
UpdateChecker(poll + notify + What's New) - src/extension.ts — wires
UpdateChecker+markItDown.updates.checkNowcommand on activation - apps/electron/main.ts —
setupAutoUpdatewiringelectron-updaterevent handlers +Check for Updates…menu item - .github/workflows/release.yml — tag-push release pipeline (matrix electron build + vsce package + release notes from CHANGELOG)
- docs/releasing.md — release runbook
- package.json —
build.publishblock (electron-updater) +markItDown.updates.checkOnLaunchsetting +markItDown.updates.checkNowcommand