Skip to content

Sprint 10: install progress, --no-use opt-out, and install/use/upgrade UX fixes (1.9.0)#19

Merged
devhardiyanto merged 3 commits into
mainfrom
fix/sprint10-ux-feedback
Jul 14, 2026
Merged

Sprint 10: install progress, --no-use opt-out, and install/use/upgrade UX fixes (1.9.0)#19
devhardiyanto merged 3 commits into
mainfrom
fix/sprint10-ux-feedback

Conversation

@devhardiyanto

Copy link
Copy Markdown
Owner

What

Sprint 10 UX feedback pass, from real usage reports on both OSes. Fixes one real crash, two output annoyances, adds live install progress, and gives install an opt-out from auto-switching. Bumps 1.8.3 -> 1.9.0.

Plan: docs/reports/arch/sprint10-ux-feedback-plan.md.

Why

Five complaints came out of actual use of phpvm install / ext install / use / upgrade. Each was traced to the source before being scoped, and the two that turned out not to be phpvm bugs were left out rather than patched blindly:

  • phpvm install composer printed a raw PowerShell stack trace. Real bug.
  • Installs went silent for minutes with no sign of life.
  • phpvm use on Windows dumped the entire five-line PHP banner.
  • phpvm upgrade on Windows still told users to restart their terminal, which stopped being true.
  • Auto-use on install (shipped in 1.8.0) is unwanted by some users, but reverting it would break everyone else's habit.

Out of scope: ext install sqlsrv (needs the real error output first — the PECL logic verifies as correct, so this is likely a missing system ODBC driver, not a phpvm bug).

How

Install crash. Invoke-Install handed any non-version string straight to Get-VSVersion, whose [int] cast threw with nothing catching it. A version guard now rejects anything that is not x.y.z before the URL resolver runs, with a Did you mean: phpvm composer hint on that specific typo. Linux never crashed here, but failed later as a misleading "Download failed" — it gets the same guard so the error names the real problem.

Progress. Modelled on how fnm does it (indicatif wrapped around the response stream): byte-level progress, drawn on stderr so stdout stays pipe-clean, and only when the content length is known.

  • Windows: Invoke-Download streams the response in chunks and prints a throttled percent / size / speed / ETA line, replacing $ProgressPreference = "SilentlyContinue". Payloads under 5 MB (Xdebug DLL, ext zips) stay silent — a bar there is just flicker. Falls back to Invoke-WebRequest when the size is unknown.
  • Linux: new _phpvm_run_logged wraps configure / make / make install with a spinner and elapsed time, returns the command's real exit code, and traps INT so Ctrl+C takes the build down instead of orphaning it.
  • Both auto-disable when stderr is not a terminal, so CI and the test suites see exactly the output they saw before.

--no-use. Auto-use stays the default; this is purely an opt-out, so no existing habit breaks. Accepted in either argument position on both OSes.

Changes

  • windows/phpvm.ps1 — version guard in Invoke-Install; --no-use parsing; Invoke-Download rewritten to stream with progress (+ Format-Bytes / Format-Duration); phpvm use prints one line; stale restart hint dropped from Invoke-Upgrade.
  • linux/phpvm.sh — matching version guard and --no-use; new _phpvm_run_logged spinner over the three build steps.
  • tests/ — 4 new Pester tests, 9 new bats tests (guard, flag parsing in both positions, exit-code propagation, and that the spinner never reaches a non-tty stream).
  • README.md, version.txt, windows/install.ps1, linux/install.sh — docs + 1.9.0.

Deliberately not mirrored across OSes

Three divergences are intentional, not missed ports:

  • Restart hint: removed on Windows, kept on Linux. phpvm.ps1 is re-executed in full on every invocation, so the next command already runs new code; phpvm.sh is sourced into the shell and genuinely needs a re-source.
  • Progress shape: a download bar on Windows vs a build spinner on Linux — Windows fetches a prebuilt zip, Linux compiles from source. There is no 1:1 here.
  • phpvm current: still prints the full banner on both. Only use was over-verbose; current was already at parity.

Testing Done

  • Pester 54/54, PSScriptAnalyzer clean
  • bats 51/51
  • Manual smoke test of the new download path is still pending. Pester excludes the Network tag, so the rewritten Invoke-Download has never actually pulled a file in CI — HTTP redirects, a missing Content-Length, or a non-interactive host would not be caught by the suite. Worth running .\windows\phpvm.ps1 install <ver> --no-use before merge.

… version

Sprint 10 UX feedback pass, phase 1 (tasks 1, 2, 6 of the plan).

- upgrade: remove "Restart your terminal" — phpvm.ps1 is re-executed in full on
  every invocation, so the next command already runs the new code. Consistent
  with B1 (1.8.2). The Linux counterpart stays: phpvm.sh is sourced into the
  shell and genuinely needs a re-source.
- use: print only the first line of `php --version`, matching Linux. `current`
  keeps the full banner on both OSes — that parity was already correct.
- install: reject anything that is not a full x.y.z before Resolve-PHPURL.
  `phpvm install composer` used to reach Get-VSVersion's [int] cast and leak a
  raw PowerShell exception; it now prints "Invalid version" plus a hint toward
  `phpvm composer`. Same guard added on Linux, where the input did not crash but
  failed later as a misleading "Download failed".

devhardiyanto
…t-out

Sprint 10 UX feedback pass, phases 2 and 3. Bumps 1.8.3 -> 1.9.0.

Progress (phase 2). Both sides went quiet for minutes during an install with no
sign of life. Modelled on fnm's approach (indicatif over the response stream):
byte-level progress, drawn on stderr so stdout stays pipe-clean, and only when
the content length is known.

- windows: Invoke-Download streams the response in chunks and prints a throttled
  percent / size / speed / ETA line, replacing $ProgressPreference=SilentlyContinue.
  Payloads under 5 MB (Xdebug DLL, ext zips) stay silent — a bar there is flicker.
  Falls back to Invoke-WebRequest when the size is unknown.
- linux: new _phpvm_run_logged wraps configure / make / make install with a
  spinner plus elapsed time, and reports the real exit code. A trap takes the
  build down on Ctrl+C instead of orphaning it.
- Both auto-disable when stderr is not a terminal, so CI and the test suites see
  the output they saw before.

--no-use (phase 3). Auto-use on install (1.8.0) is kept as the default; this only
adds an opt-out, so nobody's existing habit breaks. Accepted in either argument
position on both OSes; usage, error and hint strings are identical across them.

devhardiyanto
A trailing backslash inside single quotes reads as an escape attempt. Double
quotes with \ produce the same four frames without the ambiguity.

devhardiyanto
@devhardiyanto devhardiyanto merged commit d525ebf into main Jul 14, 2026
3 checks passed
@devhardiyanto devhardiyanto deleted the fix/sprint10-ux-feedback branch July 14, 2026 01:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant