You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(update): stop reporting an update that never installed (#46)
## Related Issue
No issue — reported directly on Windows. The problem is described below.
## Problem
A Windows user on v0.12.0 saw `Updating to v0.13.1 / Installing in the
background`, then
`↑ v0.13.1 restart to apply` under the prompt. Restarting the terminal
still gave v0.12.0, and the
update log recorded the same install as *succeeded* several times over.
`where.exe pythinker` put
`%LOCALAPPDATA%\Programs\Pythinker\pythinker.exe` first, and the
published
0.13.1 Windows binary is correct (its sha256 matches the channel
manifest and it reports 0.13.1), so
the executable that ran was the one the installer targets and the
advertised version was real. What
was wrong is that nothing ever checked. Investigating it found four
defects:
- **A success is recorded from an exit code alone.** The background
finalizer writes `lastSuccess`
when the installer exits 0. No step asks whether the binary that runs
next is the target version,
so an installer that exits 0 without replacing anything advertises
"restart to apply" forever, on
every launch.
- **`doctor` crashes on every native install.** It reports the package
root, and a packaged binary
ships no `package.json`, so the command died with
`Error: Could not locate package.json near …` — exactly when a user
needs it most. The same
lookup sits on the launch path in install-source detection.
- **npm-family auto-update cannot start on Windows.** `npm.cmd`,
`pnpm.cmd` and `yarn.cmd` are
spawned directly, which Node ≥18.20/20.12 refuses (CVE-2024-27980) with
`EINVAL`. The same call
fails in the npm-prefix lookup, so those installs also classify as
`unsupported`.
- **`install.ps1` emits no progress.** `install.sh` writes
machine-readable `progress:` lines on
stderr and the parent renders them; the PowerShell installer wrote none,
so the footer's
downloading state was unreachable on Windows and an update in flight
looked identical to a wedged
one — the defect #38 set out to close, still open on one platform.
## What changed
**A success now means the new version runs.** After an installer exits
0, the version is verified
against the artifact the installer replaced, and a mismatch is recorded
as a failure carrying the
reason (`… still reports 0.12.0 (expected 0.13.1)`) instead of a
success. Only `native` installs are
verified, by probing `process.execPath --version`: an npm global
reinstall rewrites the directory
this process was loaded from, so nothing readable there proves what the
next launch runs, and a
wrong answer would park a healthy version.
Verification fails **open** — a probe that times out (an antivirus scan
on a fresh unsigned exe is
the realistic case), cannot run, or prints no version records the
success anyway, with a note saying
why it is unproven. `doctor` prints that note next to the recorded
outcome, so the next report of
"it says updated but it did not" is answerable in one command.
**Windows package-manager shims run through the command interpreter.**
`cmd.exe /d /s /c npm.cmd …`,
spelled out as argv rather than `shell: true`, so the exact command line
is visible in the source and
asserted in tests instead of being assembled by Node's string joining.
Same fix in the npm-prefix
lookup that classifies the install source.
**`install.ps1` speaks the progress protocol**, mirroring `install.sh`:
`state=waiting` while release
assets are not up yet, `state=downloading` with percent and byte counts
(one line per second at
most), `state=done`, and a single `state=failed` after the last retry —
not between attempts, which
would drop the footer out of its downloading state and back into a
failure it is about to recover
from.
**`doctor` survives a native install**, reporting the package root only
when there is one, and the
launch-path source detection classifies an unresolvable layout as
`unsupported` rather than throwing.
It also now prints the last recorded update success, which is what would
have shown the original
problem immediately.
One scope decision worth flagging: the interactive `Updated … to X`
message still prints unchanged
when a native probe could not run. The mismatch case — the actual lie —
throws and is reported as a
failure on both foreground paths; the unproven case only loses a line in
a flow the user is watching,
and it is recorded in the install state either way.
## Checklist
- [x] I have read the
[CONTRIBUTING](https://github.com/Pythoughts-labs/pythinker-code/blob/main/CONTRIBUTING.md)
document.
- [x] I have linked a related issue, or explained the problem above.
- [x] I have added tests that prove my feature works.
- [x] Ran `gen-changesets` skill, or this PR needs no changeset.
- [x] Ran `gen-docs` skill, or this PR needs no doc update. The
user-facing docs describe the
commands, not `doctor`'s runtime lines, and the update behaviour is
unchanged when an install
really works.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
- **Bug Fixes**
- Fixed crashes when running diagnostics from native installations.
- Improved automatic updates for npm, pnpm, and Yarn installations on
Windows.
- Updates are no longer reported as successful when the installed
version remains unchanged.
- **New Features**
- Added post-update version verification with clearer failure and
unverified status reporting.
- Diagnostics now show the most recent successful update and its status.
- Windows installer downloads now display progress, waiting, completion,
and failure states.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Stop reporting an update as installed when the executable did not change; the version is checked after the installer finishes and a mismatch is recorded as a failure with the reason.
0 commit comments