Skip to content

M5 (3/3): update Botloft from inside the app, and a release workflow - #12

Merged
httpsphl merged 1 commit into
mainfrom
feat/m5-updater
Sep 29, 2026
Merged

httpsphl merged 1 commit into
mainfrom
feat/m5-updater

Conversation

@httpsphl

Copy link
Copy Markdown
Owner

Last M5 slice: in-app updates and a way to publish them.

Updates in the app

  • tauri-plugin-updater reads latest.json from the latest published GitHub release. The app checks when it opens and every 6 h. If it is offline or there is no release, nothing shows. Dev builds skip the check, so they never offer to replace themselves with the released app.
  • When a newer version exists, "Update available" appears in the title bar. The dialog says, in plain words, that Botloft will close, install and reopen, and that bots pause briefly and continue. It shows "What's new" if the release has notes. "Update now" downloads with a progress readout, then runs the installer in passive mode (/P /UPDATE /R), which reopens the app. If the update fails, the current version keeps running, the error goes under Details, and "Try again" is offered.
  • The reopened app finds the background service outdated and updates it (M5 (2/3): Botloft sets itself up, and an NSIS installer #11). The uninstall hook ignores /UPDATE, so the service keeps running until then.
  • Signing: the public key is in tauri.conf.json, the private key is the repo secret TAURI_SIGNING_PRIVATE_KEY (set), and its local copy lives in %USERPROFILE%\.tauri\botloft.key. requireSignedVersion is on, so a tampered feed cannot push an older signed release back.

Releasing

  • The version now lives only in [workspace.package] of Cargo.toml: tauri.conf.json no longer repeats it.
  • Pushing a tag vX.Y.Z runs .github/workflows/release.yml. It checks that the tag matches the version, runs pnpm bundle with the signing key, and opens a draft release containing the installer, its .sig and latest.json (app/scripts/release.mjs). Users only get offered the update once you publish the draft.

Tested

  • pnpm check: 52 tests pass, including new ones for update/no update, a failed update with retry, and an unreachable feed staying quiet. Clippy and fmt pass.
  • Local signed build with the new key and an empty password: the installer and Botloft_0.1.0_x64-setup.exe.sig are produced, and the signature's trusted comment includes version:0.1.0.
  • release.mjs check accepts v0.1.0 and rejects v0.2.0.

Manual test (needs a release)

  1. Tag v0.1.0 and push: the workflow opens a draft release with the three files. Publish it and install from it.
  2. Bump to 0.1.1, merge, tag and push, then publish the draft.
  3. With 0.1.0 open, wait up to 6 h or reopen the app: "Update available" shows. Click "Update now": Botloft closes, updates and reopens, and "Botloft" on the welcome check (or botloftd service status) reports 0.1.1.

The app checks the latest published GitHub release (latest.json) when it
opens and every six hours. A newer version shows "Update available" in
the title bar; one click downloads it with progress, runs the installer
passively and reopens Botloft, and the reopened app updates the daemon
because it is now outdated. Failures keep the current version, with the
error under "Details". Dev builds never offer to replace themselves.

Updates are signed with the Tauri updater key (public key in
tauri.conf.json, private key in the TAURI_SIGNING_PRIVATE_KEY secret),
and requireSignedVersion keeps a tampered feed from pushing an older
signed release back.

Pushing a tag vX.Y.Z runs release.yml: it checks the tag against the
workspace version, builds the signed installer and opens a draft release
with the installer, its signature and latest.json. The updater sees it
once the owner publishes it. The version now lives only in Cargo.toml.
@httpsphl
httpsphl merged commit 9d84317 into main Sep 29, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant