Skip to content

LevelCode v0.8.0

Choose a tag to compare

@github-actions github-actions released this 20 Jul 04:09
876afa9

LevelCode v0.8.0

The release that makes Check for Updates… real.

Until now that dialog always answered "There are currently no updates available." That was correct behaviour rather than a bug: the update feed deliberately refused to hand the built-in updater anything, because there was nothing it could safely install. Squirrel installs a signed .zip of the app, never a .dmg — and LevelCode only ever published dmgs.

v0.8.0 ships the missing artifact and the client-side plumbing around it. This is the first build published with update assets attached, so it is the release the update path starts from.

Highlights

Signed, notarized update assets

scripts/make-dmg.sh now emits LevelCode-<arch>.app.zip alongside the .dmgon the Developer-ID path only.

  • The dmg stays the human download (open, drag to Applications); the zip is update-only. They are not interchangeable.
  • Built with ditto -c -k --sequesterRsrc --keepParent, which preserves the stapled notarization ticket — so an app installed by an update still validates offline, with no Gatekeeper prompt. Re-zipping with zip(1) would drop it.
  • Emitted only when real Developer ID signing is used. Squirrel refuses an update whose signing identity doesn't match the running app, so an ad-hoc build can never masquerade as an update asset.
  • The zip is cut after notarization completes, never before — an unstapled app would otherwise ship.

The Download button can't hand you a raw zip

The notify-only updater's Download action preferred the feed's url. That was correct while url was a release page — but now that the feed serves the signed .app.zip there, the same code would have started a raw zip download instead of opening a page.

Download now resolves product.downloadUrl → this release's notes page → the feed base, with the install artifact dropped from the human path entirely. A future feed change cannot put a zip back behind that button.

Updates roll out behind two independent guards

The server only offers a build to the auto-installing updater when both hold: signed feed assets are declared live, and the resolved release actually has a signed zip for that architecture. Releases cut before this one therefore stay notify-only on their own, rather than relying on the rollout being performed in the right order. Architecture matching is by exact filename, so an Intel install can never be handed the arm64 build.

Under the hood

  • scripts/make-dmg.sh — emits the Squirrel update asset (plus a local-only .sha256 for hand-verifying a publish); header step list corrected to match the script, and the "unnotarized" warning scoped to the ad-hoc path it actually describes.
  • extensions/levelcode-updater/update.js — new pure downloadUrl(feed, product, base) helper.
  • extensions/levelcode-updater/extension.js — the Download action now delegates to it.
  • docs/AUTO-UPDATE.mdnew. The full feed contract, rollout order, risks, and the exit test, including which failure modes are enforced in code versus only documented.
  • docs/RELEASING.md — publishing steps updated for the second asset, and an explicit note that the .sha256 sidecars stay local (the feed reads GitHub's own asset digest).

Test coverage

  • extensions/levelcode-updater/test/update.test.js — 9 cases, 2 new, covering the Download path: the helper never returns feed.url even when that is a signed .app.zip, falls back to a page rather than an artifact, and tolerates a null feed or product. Both new cases were mutation-checked — restoring the previous preference order fails them.
  • The release CI gate continues to run the 13 levelcode-ai suites. Note the levelcode-updater tests are not part of that gate yet and are currently run manually.

Full changelog: v0.7.2...v0.8.0