fix(updater): actually check for updates on Program Files installs - #198
Open
mrjeeves wants to merge 2 commits into
Open
fix(updater): actually check for updates on Program Files installs#198mrjeeves wants to merge 2 commits into
mrjeeves wants to merge 2 commits into
Conversation
The background ticker was wired up correctly — the GUI spawns
`tick_forever`, the node spawns `tick_forever_unattended` — but on the
most common Windows install it never reached the network, and when it did
work it had no way to tell anyone.
Three separate causes, all of which made auto-update look absent:
1. `detect_install_kind` flagged ANY path under `C:\Program Files\` as
package-managed, and `check_now` bailed on that before the fetch. Our
own MSI installs there (release.yml builds `targets: "all"`, so both
the NSIS setup and the per-machine MSI ship), so every MSI install had
self-update silently switched off — the check included. Program Files
is no longer a package-manager signal; Chocolatey and Scoop still are.
Whether the install can be written is now asked at runtime with a
write probe rather than guessed from the path, which is the only
reliable test on Windows where ACLs make a permissions read
meaningless.
2. A package-managed or unwritable install now still *checks*, reporting
the new `ManualUpdateAvailable` outcome instead of returning before
the fetch. It can't install the update, but it can say one exists.
3. Every non-staging outcome was swallowed by a bare `Ok(_) => {}`, so a
ticker that was disabled and a ticker that was running fine and
finding nothing produced identical output: none, at any log level.
Each outcome is now logged.
Also: `stamp_check_now()` ran before `fetch_release`, so a failed check
burned the full 24h cooldown. It now stamps only after a successful
fetch.
Finally, the ticker held no handle to the UI, so a staged update sat on
disk until someone thought to open Settings -> Updates. `tick_forever_notify`
takes a callback; the GUI passes one that emits `update://checked`, and
the store surfaces it as a toast from anywhere in the app. "Check now" is
no longer disabled on package-managed installs, since checking works there.
Adds tests for the Windows classification (the `#[cfg(target_os =
"windows")]` branch had none) and the write probe.
gui/src-tauri/Cargo.lock picks up an unrelated 0.2.48 -> 0.2.49 sync the
release commit missed; it regenerates on any build.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FMPNLjvNYQCeR3xGfdDUCg
Every *file* layer in `init_logging` already sets `with_ansi(false)`; the stdout layer was left on tracing-subscriber's default, which is unconditionally ON — it does not check for a TTY. Under systemd that stdout is captured by journald/rsyslog, so each line reaches /var/log/syslog wrapped in escape sequences: ubuntu allmystuff-serve[793]: #33[2m2026-07-29T09:12:59Z#033[0m #33[32m INFO#033[0m … That is tens of wasted bytes on every line of a daemon that logs continuously, and it breaks grep against what you can actually read. Colour is now gated on `std::io::stdout().is_terminal()`, so a terminal still gets colour and a service gets plain text. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FMPNLjvNYQCeR3xGfdDUCg
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Auto-update looked like it never ran. The wiring was actually fine — the GUI spawns
tick_forever(gui/src-tauri/src/main.rs), the node spawnstick_forever_unattended(node/src/bin/serve.rs) — but on the most common Windows install it never reached the network, and on the installs where it did work it had no way to tell anyone.Three independent causes, each enough on its own to make the feature look absent.
What was wrong
1. Program Files was treated as a package manager.
detect_install_kind_from_pathflagged any Windows path containing\program files\asPackageManager, andcheck_nowreturned on that before the fetch. Our own MSI installs exactly there —release.ymlrunstauri-actionwith"targets": "all"and nobundle.windowsconfig, so both the per-user NSIS setup and the per-machine MSI ship. Every machine that took the MSI had self-update silently switched off, the check included.There was already an internal contradiction:
os_bundle_paths_are_left_aloneassertsC:\Program Files\AllMyStuff\allmystuff-gui.exeis safe to swap, while the check path refused to even look at it. The Windows branch was also#[cfg(target_os = "windows")], so no test on CI ever exercised it.2. A managed install checked nothing at all. Returning before the fetch meant such an install never contacted the release feed, so it could not report a new release even though it could perfectly well have done so.
3. Every non-staging outcome was swallowed.
run_attended_checkmatchedOk(_) => {}, soDisabled,PackageManager,NotDue,UpToDateandPolicyBlockedlogged nothing at any level. A ticker that was silently disabled and one running fine and finding nothing produced identical output: none. That is the hardest part of "it never checks" to diagnose.What changed
\chocolatey\lib\) and Scoop (\scoop\apps\) still are, as is Homebrew and/usr/bin. Whether an install can be written is now asked at runtime with a create/delete write probe rather than guessed from the path — the only reliable test on Windows, where ACLs make a permissions read meaningless, and exactly what the swap itself will attempt. This keeps a genuinely unwritable per-machine install from staging downloads it can never apply and retrying forever.CheckOutcome::ManualUpdateAvailable— a package-managed or unwritable install now runs the check and reports that a release exists. It can't install it; it can say so.log_check_outcome.stamp_check_now()moved after a successful fetch. It previously ran beforefetch_release, so one offline moment burned the full 24h cooldown.tick_foreverheld noAppHandle, so it structurally could not talk to the UI — a staged update sat on disk until someone happened to open Settings → Updates. Newtick_forever_notifytakes a callback; the GUI passes one that emitsupdate://checked, and the store surfaces staged / manual / policy-blocked results as a toast from anywhere in the app.Testing
cargo test -p allmystuff-updater— 22 pass, including two new ones covering the Windows classification (previously untested) and the write probe.cargo clippy -p allmystuff-updater --all-targets -- -D warningsandcargo fmt --checkclean.pnpm checkclean (155 files, 0 errors).cargo check -p allmystuff-clipasses — no consumer matches exhaustively onCheckOutcome, so the new variant is additive.The Tauri GUI crate could not be compiled in this environment (needs GTK/WebKit system libraries); that edit follows the
app.handle().clone()pattern already used a few lines above it in the same closure, and CI covers it.Note
gui/src-tauri/Cargo.lockpicks up an unrelated0.2.48→0.2.49sync of local crate versions that the release commit missed. It regenerates on any build; no third-party dependency changed.Generated by Claude Code