Update check at startup with prompt to update #12

Closed
opened 2026-10-01 21:55:17 -05:00 by deadstyle · 1 comment
Owner

Problem

Users should stay current without thinking about it. When lazyforge starts, it checks for a newer release. If there is one, it asks whether to update before continuing. If the user says yes, it updates and then starts the new version.

Plan

  1. At startup, before the TUI takes the screen, fetch the latest release from the Forgejo API with a short timeout (about 2s). If the network is down or slow, carry on silently. Startup must never hang on this.
  2. If a newer version exists, ask in plain terminal text: lazyforge v1.3.0 is available (you have v1.2.0). Update now? [Y/n], plus a one-line release summary if available.
  3. On yes: download the asset for this OS and architecture, verify it against checksums.txt, atomically replace the running binary (write a temp file next to it, then rename), and re-exec the new version with the same arguments. On any failure, say what failed and start the current version.
  4. On no: start normally.
  5. Skip the check when:
    • the build is a development build (version == "dev")
    • --no-update-check is passed
    • LAZYFORGE_NO_UPDATE_CHECK=1 is set
    • the config sets update_check: false
    • stdin is not a terminal
  6. If the binary's location isn't writable (a package manager or system install), don't offer to update in place. Show vX available, update with your package manager or install.sh instead.

Opus settles the self-replace and re-exec details (macOS code-signing caveats, Windows is out of scope) and records an ADR.

Plan-review additions (#17)

  • Failure recovery: download to a temp file beside the binary; replace only after the checksum passes, by rename (atomic on the same filesystem). Keep the old binary as lazyforge.old until the new one has started, so a failed re-exec can fall back to it and say so. A failed download, checksum or rename never leaves the install broken.
  • Package-manager detection: decide "managed install" concretely, not just "location not writable": the resolved binary path is under a Homebrew prefix (brew --prefix paths, /opt/homebrew, /usr/local/Cellar), a Nix store (/nix/store), or a system path (/usr/bin, /usr/local/bin owned by root), or isn't writable by the current user. In any of those, print the "update with your package manager or install.sh" line instead of updating.

Product questions

These are tracked in the product-decisions ticket:

  • After "no", should lazyforge ask again on every launch, or remember "skip this version"?
  • How often should it check: every launch (what was asked for), or at most once a day to keep startup fast offline?

Context

  • docs/design.md → "Install and updates".
  • Depends on the release pipeline ticket (published assets and checksums).
  • go-development → I/O rules (explicit HTTP timeouts, no http.DefaultClient).

PM decisions (2026-10-02, #13)

  • Check on every launch. No daily cache.
  • Declining asks again on the next launch. No "skip this version". The prompt stays Update now? [Y/n].
  • The "Product questions" section above is settled.
## Problem Users should stay current without thinking about it. When lazyforge starts, it checks for a newer release. If there is one, it asks whether to update before continuing. If the user says yes, it updates and then starts the new version. ## Plan 1. At startup, **before the TUI takes the screen**, fetch the latest release from the Forgejo API with a short timeout (about 2s). If the network is down or slow, carry on silently. Startup must never hang on this. 2. If a newer version exists, ask in plain terminal text: `lazyforge v1.3.0 is available (you have v1.2.0). Update now? [Y/n]`, plus a one-line release summary if available. 3. On yes: download the asset for this OS and architecture, verify it against `checksums.txt`, atomically replace the running binary (write a temp file next to it, then rename), and re-exec the new version with the same arguments. On any failure, say what failed and start the current version. 4. On no: start normally. 5. Skip the check when: - the build is a development build (`version == "dev"`) - `--no-update-check` is passed - `LAZYFORGE_NO_UPDATE_CHECK=1` is set - the config sets `update_check: false` - stdin is not a terminal 6. If the binary's location isn't writable (a package manager or system install), don't offer to update in place. Show `vX available, update with your package manager or install.sh` instead. Opus settles the self-replace and re-exec details (macOS code-signing caveats, Windows is out of scope) and records an ADR. ### Plan-review additions (#17) - **Failure recovery:** download to a temp file beside the binary; replace only after the checksum passes, by rename (atomic on the same filesystem). Keep the old binary as `lazyforge.old` until the new one has started, so a failed re-exec can fall back to it and say so. A failed download, checksum or rename never leaves the install broken. - **Package-manager detection:** decide "managed install" concretely, not just "location not writable": the resolved binary path is under a Homebrew prefix (`brew --prefix` paths, `/opt/homebrew`, `/usr/local/Cellar`), a Nix store (`/nix/store`), or a system path (`/usr/bin`, `/usr/local/bin` owned by root), or isn't writable by the current user. In any of those, print the "update with your package manager or install.sh" line instead of updating. ## Product questions These are tracked in the product-decisions ticket: - After "no", should lazyforge ask again on every launch, or remember "skip this version"? - How often should it check: every launch (what was asked for), or at most once a day to keep startup fast offline? ## Context - `docs/design.md` → "Install and updates". - Depends on the release pipeline ticket (published assets and checksums). - `go-development` → I/O rules (explicit HTTP timeouts, no `http.DefaultClient`). ## PM decisions (2026-10-02, #13) - **Check on every launch.** No daily cache. - **Declining asks again on the next launch.** No "skip this version". The prompt stays `Update now? [Y/n]`. - The "Product questions" section above is settled.
Author
Owner

🤖 Merged in #29. At startup lazyforge checks for a newer release (it gives up after 2 seconds, so offline is fine) and asks 'Update now? [Y/n]'. Yes verifies the download, swaps the binary and restarts. No carries on, and the next launch asks again. Package-manager or read-only installs just say an update is available.

🤖 Merged in #29. At startup lazyforge checks for a newer release (it gives up after 2 seconds, so offline is fine) and asks 'Update now? [Y/n]'. Yes verifies the download, swaps the binary and restarts. No carries on, and the next launch asks again. Package-manager or read-only installs just say an update is available.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
deadstyle/lazyforge#12
No description provided.