Skip to content

fix(use): prompt to install when target version missing#24

Merged
Fahl-Design merged 4 commits intomainfrom
fix/use-prompts-install-when-missing
May 8, 2026
Merged

fix(use): prompt to install when target version missing#24
Fahl-Design merged 4 commits intomainfrom
fix/use-prompts-install-when-missing

Conversation

@Fahl-Design
Copy link
Copy Markdown
Member

@Fahl-Design Fahl-Design commented May 7, 2026

Summary

  • 'pvm use ' offers install dialog when version not present locally instead of bailing with error
  • Adds hidden '--silent' flag for shell cd hooks so missing '.php-version' never blocks shell prompt with interactive question
  • 'pvm init' → "use now?" → install dialog now flows end-to-end

Repro

Reported in 'docker run --rm -it ubuntu:24.04' after fresh install:
```
$ pvm init
✓ Wrote 8.3 to .php-version
✔ Do you want to run `pvm use 8.3` now? · yes
Error: PHP 8.3 is not installed locally.
```

After this PR the user is asked whether to install, then the existing install flow runs (which also handles the "use now" prompt).

Implementation

  • 'fs::try_resolve_local_version' — Option-returning variant; 'resolve_local_version' kept as thin wrapper for callers that want an error
  • 'use_cmd::Use' gains '--silent' (hidden); when missing + non-silent, prompt → call 'install::execute_install'
  • bash/zsh/fish cd hooks call 'pvm use --silent'

Test plan

  • 'cargo fmt --check'
  • 'cargo clippy --all-targets -- -D warnings'
  • 'cargo test' (added 'test_use_silent_skips_missing_version')
  • Manual: 'pvm init' on clean container, confirm install prompt fires
  • Manual: 'cd' into dir with stale '.php-version' does not prompt

Summary by CodeRabbit

  • New Features
    • Added a hidden --silent mode for the use command to suppress prompts and allow non-interactive workflows; when a requested version is missing, silent mode exits without installing.
    • Shell hooks now invoke use in silent mode when a .php-version file exists to avoid interactive prompts on directory changes.
  • Behavior
    • Installer flow can skip the “activate now?” prompt for non-interactive installs.
  • Tests
    • Added a CLI test verifying silent use skips missing-version prompts and writes no env output.

Previously 'pvm use <ver>' bailed with an error if <ver> was not
installed locally, leaving users (notably the 'pvm init' flow) stuck.
Now the command offers to run the install dialog directly.

Adds a hidden '--silent' flag for the cd hooks so a missing
.php-version never blocks the shell prompt with an interactive
question.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 7, 2026

Review Change Stack
No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6c2aa4fd-9631-452d-88dd-6541bce7aade

📥 Commits

Reviewing files that changed from the base of the PR and between 14447d4 and d536db6.

📒 Files selected for processing (5)
  • .github/workflows/release.yml
  • src/commands/install.rs
  • src/commands/use_cmd.rs
  • src/interactive.rs
  • tests/cli.rs
✅ Files skipped from review due to trivial changes (1)
  • .github/workflows/release.yml
🚧 Files skipped from review as they are similar to previous changes (2)
  • tests/cli.rs
  • src/commands/use_cmd.rs

📝 Walkthrough

Walkthrough

The PR adds silent mode support to the use command. A new --silent flag suppresses interactive prompts when a PHP version is unavailable locally. Version resolution refactors into try_resolve_local_version returning Option<String>, enabling conditional error handling. Shell hooks invoke pvm use --silent for directory-based switching. Interactive menu and init command explicitly set silent: false for user-initiated actions.

Changes

Silent use command

Layer / File(s) Summary
Version resolution API
src/fs.rs
New try_resolve_local_version returns Option<String> on missing versions; resolve_local_version wraps it and maps None to distinct error messages.
Install activation flow
src/commands/install.rs
Introduced execute_install_with(version, prompt_activation) -> Result<Option<String>>; execute_install delegates to it. Activation prompting is conditional on prompt_activation; cancelled selection returns Ok(None).
CLI flag definition
src/commands/use_cmd.rs
Added hidden silent: bool field to Use struct.
Use command implementation
src/commands/use_cmd.rs
Updated Use::call to detect missing versions via try_resolve_local_version; returns Ok(()) immediately if silent is set, otherwise prompts to install and invokes installer with controlled activation prompting.
Init command integration
src/commands/init.rs
Sets silent: false when constructing Use after writing .php-version.
Interactive menu updates
src/interactive.rs
Menu "Use" options explicitly set silent: false alongside version field.
Shell hook generation
src/shell.rs
Bash, Zsh, and Fish hooks invoke pvm use --silent when switching based on .php-version.
Test coverage
tests/cli.rs
Added test for use --silent with missing version; verifies success without output and no env-update file creation.
CI Workflow
.github/workflows/release.yml
Add client-id: ${{ secrets.BOT_APP_ID }} to token generation steps in release and build jobs.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • WebProject-xyz/php-version-manager#6: Modifies the same files (src/commands/use_cmd.rs, src/fs.rs, src/commands/init.rs, src/shell.rs) for version resolution and use command behavior changes.

Suggested labels

enhancement

🐰 I hopped in quiet, no alarms,
.php-version charms without the harms,
Hooks whisper, versions glide,
Silent switches — hop with pride,
Shell and tests sing soft and calm.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 38.46% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix(use): prompt to install when target version missing' directly and clearly describes the main behavior change: the 'use' command now prompts to install missing versions instead of failing.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/use-prompts-install-when-missing

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@Fahl-Design Fahl-Design self-assigned this May 7, 2026
@Fahl-Design
Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 7, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
tests/cli.rs (1)

128-140: ⚡ Quick win

Strengthen assertions to match the documented silent-mode contract

The comment at line 138 states "exits 0 with no output and no env file written", but only the exit code is verified. The predicates crate is already imported; adding stdout/stderr checks is a one-liner.

✅ Proposed fix
-    // Silent mode: missing version exits 0 with no output and no env file written.
-    cmd.assert().success();
+    // Silent mode: missing version exits 0 silently.
+    cmd.assert()
+        .success()
+        .stdout(predicate::str::is_empty())
+        .stderr(predicate::str::is_empty());
+
+    // Env file should not have been written
+    assert!(!temp_dir.path().join("pvm_env_update").exists());

As per coding guidelines: "Use assert_cmd and predicates crates for CLI output and exit code verification in integration tests."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/cli.rs` around lines 128 - 140, The test
test_use_silent_skips_missing_version currently only asserts success; update it
to also assert that both stdout and stderr are empty by chaining
.stdout(predicate::str::is_empty()) and .stderr(predicate::str::is_empty()) on
cmd.assert(), and after running the command verify that no env file was written
in the temporary PVM_DIR (e.g., check temp_dir.path() has no new env file by
asserting the directory has no entries or that the specific env filename is
absent) so the test enforces "no output and no env file written".
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/commands/use_cmd.rs`:
- Around line 23-48: The branch that handles a missing local version returns
immediately after calling crate::commands::install::execute_install(v). Instead,
after a successful install, call fs::try_resolve_local_version(v) again and
assign its Some(resolved) to the same resolved/version binding so execution
falls through to the existing activation logic (the env-file write,
PVM_MULTISHELL_PATH assignment and PATH update) rather than returning early;
update the Some(ref v) match arm in use_cmd.rs to re-resolve post-install and
proceed to the activation path when resolution succeeds, handling the silent and
cancel cases as before.

In `@src/interactive.rs`:
- Around line 51-57: Match arm 3 is dispatching to the wrong command: it
constructs commands::use_cmd::Use instead of the list command, causing the "List
(View locally installed versions)" menu option to open the version-switcher.
Replace the construction in the arm with the list command (e.g., construct and
call commands::list_cmd::List with the appropriate fields or empty struct if
none) so the arm invokes List::call().await rather than Use::call().await;
update the match arm that currently references commands::use_cmd::Use to
reference commands::list_cmd::List.

---

Nitpick comments:
In `@tests/cli.rs`:
- Around line 128-140: The test test_use_silent_skips_missing_version currently
only asserts success; update it to also assert that both stdout and stderr are
empty by chaining .stdout(predicate::str::is_empty()) and
.stderr(predicate::str::is_empty()) on cmd.assert(), and after running the
command verify that no env file was written in the temporary PVM_DIR (e.g.,
check temp_dir.path() has no new env file by asserting the directory has no
entries or that the specific env filename is absent) so the test enforces "no
output and no env file written".
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2851a3d0-2c9e-461f-9594-94cbbf92b88a

📥 Commits

Reviewing files that changed from the base of the PR and between 4f6c2b4 and 14447d4.

📒 Files selected for processing (6)
  • src/commands/init.rs
  • src/commands/use_cmd.rs
  • src/fs.rs
  • src/interactive.rs
  • src/shell.rs
  • tests/cli.rs

Comment thread src/commands/use_cmd.rs
Comment thread src/interactive.rs
…u correctly

Addresses CodeRabbit review on #24:

- use_cmd: after the install prompt accepts and the install runs, fall
  through to the activation path with the freshly resolved version
  instead of returning early. Otherwise the user's shell was never
  switched and they had to run 'pvm use <ver>' a second time.
- install: 'execute_install_with(version, prompt_activation)' returns
  the resolved version so callers can chain activation themselves;
  legacy 'execute_install' kept as a thin wrapper for the standalone
  'pvm install' command.
- interactive: menu index 3 ('List') now dispatches to ls::Ls; it was
  previously wired to use_cmd::Use, opening the version-switcher.
actions/create-github-app-token v3 deprecated the 'app-id' input in
favor of 'client-id'. The new input still accepts an App ID value, so
the existing BOT_APP_ID secret continues to work unchanged. This
silences the eight deprecation warnings emitted on every workflow run.
Strengthen test_use_silent_skips_missing_version per CodeRabbit
feedback: with PVM_ENV_UPDATE_PATH pointed at a known path inside the
tempdir, assert stdout/stderr are empty and that the env file was
never created when the requested version is absent.
@Fahl-Design
Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 7, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot added the enhancement New feature or request label May 7, 2026
@Fahl-Design Fahl-Design merged commit ceec711 into main May 8, 2026
4 checks passed
@Fahl-Design Fahl-Design deleted the fix/use-prompts-install-when-missing branch May 8, 2026 17:32
webproject-bot Bot pushed a commit that referenced this pull request May 8, 2026
## [1.2.1](v1.2.0...v1.2.1) (2026-05-08)

### Bug Fixes

* **use:** prompt to install when target version missing ([#24](#24)) ([ceec711](ceec711))
@webproject-bot
Copy link
Copy Markdown

webproject-bot Bot commented May 8, 2026

🎉 This PR is included in version 1.2.1 🎉

The release is available on:

Your semantic-release bot 📦🚀

Fahl-Design added a commit that referenced this pull request May 8, 2026
Refactor the monolithic fpm-readme.sh into:
  tests/e2e/run.sh             driver
  tests/e2e/_lib.sh            shared helpers (run_under_expect, fcgi_call)
  tests/e2e/cases/NN_*.sh      one file per case

The driver runs each case in a fresh bash subprocess, so state from
one case can no longer hide bugs in the next (the previous monolith
silently passed because pvm's 24h .update_check_guard suppressed the
patch-update prompt for any case after the first one to use it).

Coverage now includes (Linux, ubuntu-latest):
  01 real `pvm install` flow with interactive MultiSelect (expect)
  02 pvm ls discovers [cli, fpm]
  03 pvm use through shell wrapper switches PATH; which php-fpm
  04 pvm current after pvm use
  05 .php-version cd-hook auto-switch
  06 pvm use <missing-version> → install prompt + decline (#24)
  07 patch-update detection on pvm use <minor>
  08 README php-fpm.conf + pool.d/{www,sock}.conf passes -t
  09 fpm -F listens on TCP :9000 + unix /tmp/php-fpm-www.sock
  10 FastCGI roundtrip over TCP returns FCGI_OK
  11 FastCGI roundtrip over unix socket returns FCGI_OK
  12 -c php.ini effective inside worker (memory_limit, expose_php)
  13 pid file + error log written
  14 SIGQUIT clean shutdown
  15 pvm uninstall removes the version directory

CI job in release.yml renamed to "e2e tests - linux", chained between
the existing `tests` and `release` jobs. apt-get installs expect and
libfcgi-bin (for cgi-fcgi) on top of netcat-openbsd. The suite targets
PHP 8.5 by default (PVM_VERSION_MAJOR_MINOR=8.5), overridable per env.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request released

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant