Skip to content

Releases and updates

The desktop app updates itself. Each release is built and signed by CI and published to one downloads address. Installed apps and the hub’s download page both read it.

The first half of this page is for everyone who uses the app. The second half is for the people who make releases. Their full guide, with every secret and command, is docs/RELEASING.md in the Sift repository.

flowchart LR
  TAG["Version tag<br/>(v0.2.0)"] --> CI["CI builds for macOS,<br/>Windows and Linux,<br/>signs and notarises"]
  CI --> DL[("Downloads address<br/>installers and<br/>latest.json")]
  DL --> APP["Installed apps check<br/>latest.json, download,<br/>then 'Restart to update'"]
  DL --> PAGE["The hub's<br/>download page"]

Once per launch, the app checks for a newer release. If there is one, it downloads it in the background and shows a small card in the bottom-left corner:

  1. “Sift 0.2.1 is available”, with the download’s progress. Keep working.
  2. “Sift 0.2.1 is ready”, with Restart to update and Later.

The app never restarts by itself. It waits until you choose Restart to update. Your work is saved, and syncing picks up again after the restart. If you are offline, the app checks when the network comes back.

To check yourself, open the account menu at the bottom of the sidebar and choose Check for updates…. The card then also tells you when Sift is up to date, or what went wrong. When an update is waiting, the same menu offers Restart to update to followed by the version.

If you choose Later, the card goes away. The account menu still offers the update.

If the account menu has no Check for updates…, this build doesn’t update itself. Install new versions from your organisation’s download page.

  • macOS: the app is replaced.
  • Windows: the installer runs with a progress bar and no questions.
  • Linux: the AppImage replaces itself. A .deb or .rpm install asks for an admin password to install the new package.

Every hub has a public download page at its address followed by /download. You don’t need to sign in, so you can send the link to new people.

It shows the newest version and its release date, and offers the installer for your computer first. Below that it lists every installer with its size and SHA-256 checksum. To check a download, run shasum -a 256 <file> (macOS, Linux) or Get-FileHash <file> (Windows) and compare.

  • macOS: open the .dmg and drag Sift to Applications.
  • Windows: if Windows shows “Windows protected your PC”, choose More info, then Run anyway. The Windows installer isn’t code-signed yet.
  • Linux: make the AppImage executable (chmod +x) and run it. It updates itself. The .deb and .rpm packages install system-wide.

If the page says “No release has been published yet”, nothing is on the downloads address yet. If it says “Downloads aren’t set up for this Hub”, the hub web app was built without a downloads address.

The app’s version is the version in package.json. npm run brand copies it into the Tauri configuration, and src-tauri/Cargo.toml must carry the same version. Each version can be published once. To fix a release, publish the next patch version.

Each signer is optional and turns on when its secrets are set on the repository. A signer with only some of its secrets fails the run at once.

  • macOS: a Developer ID certificate and an App Store Connect API key. The app and the .dmg are signed, notarised and stapled.
  • Windows: Azure Trusted Signing. Not in use yet, so Windows installers are unsigned.
  • In-app updates: the update signing key, plus its public half in brand.json as updaterPubkey. Without it, apps don’t update themselves.
  • Downloads bucket: the Cloudflare R2 account, keys and bucket. Without them, nothing is uploaded.

Keep the update signing key and its password safe. If they are lost, installed apps can never update again, and everyone has to reinstall by hand.

  1. Bump the version on a branch and merge it into main with CI green.
  2. Optionally, run the build workflow by hand on main and try its installers. That makes no release.
  3. Tag the merge commit with v and the version, for example v0.2.0, and push the tag. The tag must match the app’s version.
  4. CI builds for macOS (Apple silicon and Intel), Windows and Linux, which takes 20 to 40 minutes. When every build succeeds, it drafts a GitHub release and uploads the installers and latest.json to the downloads address.
  5. Check latest.json at the downloads address, open /download on the hub, and install at least one build.
  6. Edit the draft’s notes and publish it. The GitHub copy is the archive.

The upload is the real release. From the moment latest.json is written, the download page offers it and installed apps update to it. Pre-release versions such as 1.2.0-beta.1 are uploaded but never offered.

A failed build uploads nothing. Fix it, delete the tag, and tag again.

To stop offering a bad release, point latest.json back at the previous version’s copy, then ship the fix as a new version. Apps that already updated stay on the bad version until then.

Do this once after setting up the update key, and on each operating system you support:

  1. Release a version, say 0.2.0, and install it from /download on a test machine.
  2. Release 0.2.1 with no other changes.
  3. Start the installed 0.2.0, or choose Check for updates…. The card shows that 0.2.1 is available, the download, then Restart to update. Wait a minute to see that nothing restarts on its own, then press it. The app comes back as 0.2.1.

If the card never appears, check that latest.json names a newer version and lists your platform. A signature mismatch means the build’s updaterPubkey doesn’t match the key that signed the update.

The hub is released separately, from hub-v* tags, as a container image. See Deploy and run the hub.