Skip to content

feat(desktop): install downloaded updates on quit - #358

Merged
incognitojam merged 4 commits into
mainfrom
styal/install-updates-on-quit
Sep 17, 2026
Merged

incognitojam merged 4 commits into
mainfrom
styal/install-updates-on-quit

Conversation

@incognitojam

@incognitojam incognitojam commented Sep 17, 2026 •

Copy link
Copy Markdown
Owner

Note

Desktop updates download quietly and install on normal quit. Native macOS and Windows testing verified channel-switch safety, installation, and restart. macOS testing also verified failure fallback and exposed a shutdown race fixed in this PR.

What Changed

Downloaded desktop updates now install automatically on normal quit, ready for the next launch. The sidebar stays quiet during checks and downloads, and shows its restart icon only when an update is ready to install. Settings retains manual checks, download progress, and retries; choosing restart still asks for confirmation.

Why

Background downloads previously required an explicit update-and-restart action, even when the user quit normally. Remove the sidebar’s check/download controls and animation state. Ordinary shutdown closes the window and waits for backend cleanup, then styal installs only a ready download matching the selected update track. The updater’s unconditional install-on-quit flag stays disabled: changing tracks clears installation eligibility, and macOS native staging is deferred until this final decision. Native staging errors or a 30-second handoff timeout fall back to ordinary quit; the native relaunch policy is set explicitly for quit versus restart. A one-shot final-window listener survives cleanup so Electron’s default quit cannot bypass update staging. On macOS, closing the last window leaves the app running; installation requires quitting.

Validation

  • 89 focused tests pass on Linux, macOS, and Windows across updater, Electron adapter, lifecycle, application menu, and UI-state suites. They cover startup/background downloads, channel switches followed by failed checks/no update/failed replacement download/successful replacement, ignored old-channel completion events, shutdown-before-install ordering, a late native close after scoped listeners are removed, native staging failure/timeout, no relaunch on normal quit, and sidebar states.
  • Desktop and web typechecks, targeted lint, formatting, and the fork ledger check pass.
  • Desktop-only change. Shared sidebar footer covers the desktop sidebar layouts; Settings keeps the existing controls. Remote service updates, providers, wire contracts, and mobile are unaffected.

Browser Validation

Exercised the real client against isolated server state with a synthetic project and simulated Electron update bridge. The final pass verified that idle, checking, downloading, and download failures show no sidebar update button; a downloaded update shows the restart icon; cancel sends no install request; confirm sends exactly one; installation failure keeps the retry icon. Settings still displays downloading status and invokes download retry and manual checks. Navigating into and out of Settings worked, with no page errors in the final pass. The native installer was simulated, not invoked. Console inspection found unrelated Clerk production-key origin errors on localhost; styal Link sign-in was not part of this pass.

UI Evidence

Before and after the change, with a download in progress:

Before After
Before: sidebar download progress After: background download has no sidebar indicator

Once downloaded, the restart icon and release notes remain available:

After: ready-to-restart icon and release notes

Checking → downloading → ready, before:

install-on-quit-before.mp4

Checking → downloading → ready, after:

install-on-quit-after.mp4

Native macOS Validation

Exercised real Electron 41.5.0 and Squirrel.Mac on Apple Silicon/macOS 27 using Developer ID signed test bundles, an isolated bundle ID, separate app data and updater caches, and a local update feed. Test versions were 9.0.0, 9.0.1-nightly.20260917.1, and 9.0.1; installation was not stubbed.

  • Download nightly → switch to stable → failed check: ready state clears; Quit leaves the original version installed, confirmed again on next launch.
  • Download nightly → switch to stable → no update: ready state clears; Quit leaves the original version installed.
  • Download nightly → switch to stable → download stable: Quit installs stable and leaves the app closed.
  • Quit with a downloaded update and the window still open: after fixing the late-window-close race, the bundle is replaced and the app remains closed. Observed shutdown including native staging took roughly 3–4 seconds; this is a test observation, not a performance guarantee.
  • Close the last macOS window with an update downloaded: the process remains running on the old version; actual Quit installs the update. A subsequent launch opens the installed version.
  • Explicit restart: the old process exits, the bundle updates, and a new app process opens automatically.
  • Corrupt the isolated downloaded archive before Quit: native staging reports an error; ordinary quit still completes and keeps the old version. The next launch detects the invalid cache and downloads a fresh copy.

Native Windows Validation

Exercised real Electron and NSIS installers on Windows 11 x64 using an isolated app identity, installation directory, app data, updater cache, and local update feed. Test versions were 9.0.0, 9.0.1-nightly.20260917.1, and 9.0.1; installation was not stubbed.

  • Download nightly → close the last window: NSIS installs nightly and leaves the app closed; the next launch reports the nightly version.
  • Download nightly → switch to stable → failed check: ready state clears; Quit leaves 9.0.0 installed and the app closed.
  • Download nightly → switch to stable → no update: ready state clears; closing the window leaves 9.0.0 installed and the app closed.
  • Download nightly → switch to stable → download stable: closing the window installs 9.0.1, with no automatic relaunch.
  • Explicit restart: NSIS replaces 9.0.0 with 9.0.1 and automatically opens the updated app window. Closing that window exits normally.
  • Windows packaged payload validation passes, including 61 files and 26 sidecar native modules; all 89 focused tests pass against the PR runtime source.

Windows fixtures were unsigned and used a copied resource-monitor binary. Test-only build preparation normalized Windows archive paths and moved payload validation outside the checkout; fixture identity/feed settings were isolated from the real installation. These runs do not verify Authenticode, WSL backend behavior, production installer migration hooks, or release packaging performance. Immediate reopening during native installation and macOS notarization remain unverified.


Written by an agent (Codex, GPT-6).

@incognitojam
incognitojam marked this pull request as ready for review September 17, 2026 13:57
@incognitojam
incognitojam merged commit fafef1b into main Sep 17, 2026
16 checks passed
@incognitojam
incognitojam deleted the styal/install-updates-on-quit branch September 17, 2026 14:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant