Repository navigation
feat(upgrade): self-upgrade on Windows - #26
Conversation
…binary in A running .exe can't be overwritten on Windows, but it can be renamed. Install into a staging folder beside the binary, and only after install.sh exits 0 rename the running binary to docx.exe.old and the staged one into place. A failed or interrupted upgrade leaves docx.exe untouched.
|
🤖 docx-cli triage Thanks @xsvm, this is a careful PR. The "nothing moves until install.sh exits 0" ordering is the right design, and the reasoning in the What the PR claims
Supply-chain check (installer invariant)
What I verified (Linux, at bdbc6db)I had no real Windows machine, so I reviewed the Windows path by reading the code only. Renaming a running Findings
Questions for @kklimuk
Action needed: answer the questions above — whether Windows self-upgrade is wanted (and the Windows CI coverage expectation); if yes, ask the author for fixes 1–3 before merging. Generated by Claude Code |
…staging PATH note
- swapIn renames the running binary back when moving the staged one in
fails (antivirus often holds a fresh .exe open), so the user is never
left with only docx.exe.old; upgrade reports UPGRADE_FAILED as
{code,error,hint} and always removes the staging folder.
- On Windows install.sh's closing PATH note named the staging folder,
which upgrade deletes right after; withoutStagingPathHint drops those
lines from the forwarded stdout. install.sh is untouched.
- The renamed-binary guard compares case-insensitively on Windows.
- SECURITY.md no longer says Windows must upgrade by hand, and the
docx upgrade entry describes the staging swap.
Follows the triage review on kklimuk#26.
A native C:\...\.docx-upgrade PREFIX put backslashes in the downloaded
file's path. GNU sha256sum (Git Bash) escapes such a name and prefixes its
output line with a backslash, which install.sh's awk '{print $1}' keeps, so
every Windows upgrade failed with "SHA-256 mismatch" (actual hash shown with
a leading backslash). Found by running docx upgrade on Windows 11 / Git Bash;
with a C:/... PREFIX it verifies, swaps in the release binary, and removes the
staging folder. install.sh is unchanged.
|
Thanks for the review. I've pushed fixes 1–3 and the case-sensitivity point. I also have a real Windows machine (Windows 11, Git Bash), so I ran
The first real run downloaded v0.28.0 and then refused to install it: This is your third minor point (a native PREFIX handed to MSYS With that fix, the second real run: Afterwards Separately, install.sh would be more robust if it hashed from stdin (
|
|
🤖 docx-cli triage Thanks @xsvm. The follow-ups do what you said, and the checksum bug you found on Windows is a good catch. I re-reviewed at Prior findings, re-checked
Supply-chain check (installer invariant)
What I ran (Linux, at 541ca5c)The one failure is Optional nit (not blocking)In the antivirus case that the rollback exists for, Decisions for @kklimuk
I pushed nothing. The contributor made the last push, so your own approval satisfies the last-push rule. Action needed: answer question — decide whether Windows self-upgrade is wanted and whether a Windows CI job is required. If yes, approve and merge PR #26 (your approval alone satisfies the last-push rule, since I pushed nothing). Separately, decide on the install.sh stdin-hashing follow-up. Generated by Claude Code |
|
@xsvm hold off from making further changes till i've had a bit of time to read through and do my own reviews, it's gonna take me a few days. |
GNU sha256sum escapes a file name holding a backslash by prefixing its output line with `\`, which landed in the digest and failed the comparison. Every checksum tool now reads stdin, so no file name reaches its output. v0.28.0's Windows binary embeds install.sh with CRLF line endings, because the Windows runner checks text out that way and the checked-out bytes are what the binary ships. .gitattributes pins *.sh to LF. build-binary now runs on windows-latest, and every platform does a real `docx upgrade` to a pinned release. The Windows unit-test pass is informational until its known failures are fixed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…p fails A throw from the staging cleanup in `finally` replaced the result, so even a successful swap could exit nonzero. And when the rollback rename failed too, the error still said the binary was unchanged; it now names docx.exe.old. Also notes that Windows binaries up to v0.28.0 need one last manual swap. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On the Windows runner Bun.which found a shasum that sh can't execute, so the test failed on a tool install.sh would never pick. Ask sh with command -v, the same check install.sh uses. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
🤖 docx-cli triage Three new commits landed on this PR since my last review (
So I haven't fetched or executed this head and I'm leaving the PR to the maintainer to review by hand (labelled Action needed: inspect a suspicious PR — confirm Generated by Claude Code |
Summary
docx upgraderefused on Windows because a running.execan't be overwritten,so Windows users had to download and swap the binary by hand. Windows does let
you rename a running
.exe, andinstall.shalready supports Git Bash/MSYS(it picks
docx-windows-x64.exeand writesdocx.exe). So:install.shgetsPREFIX=<dir>/.docx-upgradeand installs there.It's the same download and the same checksum gate.
swapIn(src/cli/upgrade/swap-in.ts) renames therunning binary to
docx.exe.oldand the staged one into its place. Thestaging folder is removed either way.
.oldfile can't delete itself while it runs, so the next upgraderemoves it.
interrupted upgrade therefore leaves
docx.exeexactly as it was, so there'sno restore path and no signal handling. I tried stepping aside first and
restoring on failure, but Ctrl+C can't be trapped reliably on Windows: MSYS
shon piped stdio ignores it, so a Ctrl+C mid-download could leave nodocxat all.docx.exeon Windows (the samename rule
install.shuses).shisn't on PATH (cmd/PowerShell without Git Bash), it refuses up frontand points to Git Bash or a manual swap.
logic in TypeScript.
Docs:
--help, README, SECURITY.md, troubleshooting.md,src/cli/CLAUDE.md.Test plan
bun run checktests/cli/upgrade.test.ts: a new swap-in case (staged → in place, old→
.old, previous.oldswept). It's plain file moves, so it runs onevery OS.
.exesuffix,platform path separator). It used to fail there.
-
upgrade --to v0.0.1: install fails on the missing SHA256SUMS,docx.exeis untouched, and no staging folder is left behind-
upgrade --to v0.27.0with the download held open (the proxy pointsat a socket that never answers), then the terminal is killed:
docx.exeis untouched and still runs, and the next upgrade clears thestaging leftovers
- I didn't run a full successful download. That path is
install.sh'snormal Git Bash install into the staging folder, followed by the two
renames the unit test covers.