fix(prepare): install config tools before running prepare steps#8582
fix(prepare): install config tools before running prepare steps#8582
Conversation
`InstallOptions::default()` sets `missing_args_only: true`, which skips tools from `[tools]` config and only installs CLI-argument tools. This caused prepare steps to run before their required tools were installed, failing on clean machines where tools like `uv` aren't available system-wide. Fixes #8567 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request addresses a critical issue where mise's prepare steps could fail on environments without pre-installed tools. By modifying the tool installation logic, it ensures that all necessary tools specified in configuration files are installed before any prepare steps are executed, preventing failures and improving the reliability of mise in new or clean development environments. Highlights
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
Greptile SummaryThis PR fixes a race condition where Key changes:
The Confidence Score: 3/5
Important Files Changed
Sequence DiagramsequenceDiagram
participant User
participant prepare_rs as mise prepare / mise run
participant Toolset
participant PrepareEngine
participant PrepareCommand
User->>prepare_rs: invoke command
prepare_rs->>Toolset: build toolset (ToolsetBuilder)
prepare_rs->>Toolset: install_missing_versions(missing_args_only: false)
Note over Toolset: Installs ALL config [tools] (e.g. uv, tiny)<br/>Before fix: missing_args_only was true,<br/>skipping config tools
Toolset-->>prepare_rs: tools installed, shims rebuilt
prepare_rs->>Toolset: env_with_path() → PATH includes new tools
prepare_rs->>PrepareEngine: run(PrepareOptions { env: toolset_env })
PrepareEngine->>PrepareCommand: from_string(run, config)
Note over PrepareCommand: Wraps in default_inline_shell()<br/>(sh -c) to support pipes/redirects
PrepareCommand-->>PrepareEngine: PrepareCommand { program: "sh", args: ["-c", run] }
PrepareEngine->>PrepareEngine: execute_prepare_static(cmd, toolset_env)
Note over PrepareEngine: Runs with PATH containing installed tools
PrepareEngine-->>prepare_rs: PrepareStepResult::Ran(id)
prepare_rs-->>User: "Prepared: {id}"
Last reviewed commit: 288b0c4 |
There was a problem hiding this comment.
Code Review
This pull request correctly fixes an issue where tools from config files were not installed before prepare steps in mise run and mise prepare. The change involves setting missing_args_only: false when installing tools. My review includes a couple of minor suggestions to improve code conciseness by inlining the InstallOptions struct where it's used only once.
| let install_opts = InstallOptions { | ||
| missing_args_only: false, | ||
| ..Default::default() | ||
| }; | ||
| ts.install_missing_versions(&mut config, &install_opts) | ||
| .await?; |
There was a problem hiding this comment.
For conciseness, you can construct InstallOptions inline within the install_missing_versions call, since the install_opts variable is not used elsewhere.
| let install_opts = InstallOptions { | |
| missing_args_only: false, | |
| ..Default::default() | |
| }; | |
| ts.install_missing_versions(&mut config, &install_opts) | |
| .await?; | |
| ts.install_missing_versions(&mut config, &InstallOptions { | |
| missing_args_only: false, | |
| ..Default::default() | |
| }) | |
| .await?; |
| let opts = InstallOptions { | ||
| jobs: self.jobs, | ||
| raw: self.raw, | ||
| missing_args_only: false, | ||
| ..Default::default() | ||
| }; | ||
| let _ = ts.install_missing_versions(&mut config, &opts).await?; |
There was a problem hiding this comment.
For conciseness, you can construct InstallOptions inline within the install_missing_versions call, since the opts variable is not used elsewhere.
| let opts = InstallOptions { | |
| jobs: self.jobs, | |
| raw: self.raw, | |
| missing_args_only: false, | |
| ..Default::default() | |
| }; | |
| let _ = ts.install_missing_versions(&mut config, &opts).await?; | |
| let _ = ts.install_missing_versions(&mut config, &InstallOptions { | |
| jobs: self.jobs, | |
| raw: self.raw, | |
| missing_args_only: false, | |
| ..Default::default() | |
| }).await?; |
Ensures tools from [tools] config are installed before prepare steps that depend on them, preventing regression of the ordering fix. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Custom prepare commands were executed directly (splitting into program + args) which meant shell features like pipes, redirects, and && didn't work. Now wraps commands with the default inline shell (sh -c) to match task execution behavior. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Match the pattern from task_tool_installer.rs: honor task.run_auto_install and auto_install settings so users who set auto_install = false don't get config tools force-installed. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Use cmd.description (the original run string) instead of the shell-wrapped program+args in --explain output. Restores precise assertion in e2e test. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
mise prepare is an explicit user command like mise install, so it should always install config tools regardless of auto_install setting. The auto_install guard is only appropriate for implicit installs (shims, mise x, mise run). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace unwrap() with a proper error message if the user has configured an empty shell string. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Hyperfine Performance
|
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.3.8 x -- echo |
23.7 ± 0.4 | 22.9 | 28.9 | 1.00 |
mise x -- echo |
23.7 ± 0.6 | 22.8 | 29.2 | 1.00 ± 0.03 |
mise env
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.3.8 env |
23.8 ± 0.6 | 22.5 | 25.3 | 1.00 |
mise env |
24.3 ± 0.5 | 23.0 | 26.6 | 1.02 ± 0.03 |
mise hook-env
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.3.8 hook-env |
24.9 ± 0.6 | 23.7 | 32.2 | 1.00 |
mise hook-env |
25.0 ± 0.8 | 23.2 | 27.6 | 1.00 ± 0.04 |
mise ls
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.3.8 ls |
24.4 ± 0.7 | 22.9 | 29.9 | 1.00 ± 0.04 |
mise ls |
24.3 ± 0.7 | 22.5 | 27.2 | 1.00 |
xtasks/test/perf
| Command | mise-2026.3.8 | mise | Variance |
|---|---|---|---|
| install (cached) | 152ms | 153ms | +0% |
| ls (cached) | 84ms | 84ms | +0% |
| bin-paths (cached) | 86ms | 86ms | +0% |
| task-ls (cached) | 849ms | 824ms | +3% |
### 🚀 Features - **(github)** use release latest endpoint to get latest release by @roele in [#8516](#8516) - **(install)** add shared and system install directories by @jdx in [#8581](#8581) - **(vfox)** add provenance metadata to lockfile for tool plugins by @malept in [#8544](#8544) ### 🐛 Bug Fixes - **(aqua)** expose main binary when files field is empty and symlink_bins is enabled by @AlexanderTheGrey in [#8550](#8550) - **(env)** redact secrets in `mise set` listing and task-specific env by @jdx in [#8583](#8583) - **(prepare)** install config tools before running prepare steps by @jdx in [#8582](#8582) - **(task)** allow ctrl-c to interrupt tool downloads during `mise run` by @jdx in [#8571](#8571) - **(tasks)** add file task header parser support for spaces around = by @roele in [#8574](#8574) ### 📚 Documentation - **(task)** add property description for interactive by @roele in [#8562](#8562) - add missing `</bold>` closing tag by @muzimuzhi in [#8564](#8564) - rebrand site with new chef logo and warm culinary palette by @jdx in [#8587](#8587) ### 📦️ Dependency Updates - update ghcr.io/jdx/mise:alpine docker digest to de4657e by @renovate[bot] in [#8577](#8577) - update ghcr.io/jdx/mise:copr docker digest to eef29a2 by @renovate[bot] in [#8578](#8578) - update ghcr.io/jdx/mise:rpm docker digest to 5a96587 by @renovate[bot] in [#8580](#8580) - update ghcr.io/jdx/mise:deb docker digest to 464cf7c by @renovate[bot] in [#8579](#8579) ### 📦 Registry - fix flatc version test mismatch by @jdx in [#8588](#8588) ### Chore - **(registry)** skip spark test-tool by @jdx in [#8572](#8572) ### New Contributors - @AlexanderTheGrey made their first contribution in [#8550](#8550) ## 📦 Aqua Registry Updates #### New Packages (6) - [`bahdotsh/mdterm`](https://github.com/bahdotsh/mdterm) - [`callumalpass/mdbase-lsp`](https://github.com/callumalpass/mdbase-lsp) - [`facebook/ktfmt`](https://github.com/facebook/ktfmt) - [`gurgeous/tennis`](https://github.com/gurgeous/tennis) - [`tektoncd/pipelines-as-code`](https://github.com/tektoncd/pipelines-as-code) - [`weedonandscott/trolley`](https://github.com/weedonandscott/trolley) #### Updated Packages (2) - [`apple/container`](https://github.com/apple/container) - [`cocogitto/cocogitto`](https://github.com/cocogitto/cocogitto)
…8582) ## Summary - `InstallOptions::default()` sets `missing_args_only: true`, which only installs tools passed as CLI arguments — not tools from `[tools]` in config files - This caused prepare steps to run before their required tools were installed, failing on clean machines where tools like `uv` aren't available system-wide - Set `missing_args_only: false` in both `mise run` and `mise prepare` so config tools are installed before prepare steps execute Fixes jdx#8567 ## Test plan - [x] Verified with a test project using `[tools] uv = "0.9.25"` and a custom prepare step that runs `uv pip install` - [x] Before fix: prepare runs before uv is installed (uses system uv if available, fails on clean machines) - [x] After fix: uv is installed first, then prepare runs successfully - [ ] CI passes 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Changes tool auto-install behavior for `mise prepare`/`mise run` and alters how prepare commands are executed (now via an inline shell), which could affect projects relying on previous argument parsing or auto-install settings. > > **Overview** > Ensures `mise prepare` installs all configured `[tools]` before executing prepare rules by setting `InstallOptions.missing_args_only` to `false`, preventing prepare steps from failing on clean machines. > > Aligns prepare command execution with task behavior by wrapping `PrepareCommand::from_string` in the configured inline shell (enabling pipes/redirects/`&&`) and updates `--explain` output to show the command description. Adds an e2e regression test (`test_prepare_tool_install`) that verifies tool installation occurs before the prepare step runs. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 288b0c4. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
### 🚀 Features - **(github)** use release latest endpoint to get latest release by @roele in [jdx#8516](jdx#8516) - **(install)** add shared and system install directories by @jdx in [jdx#8581](jdx#8581) - **(vfox)** add provenance metadata to lockfile for tool plugins by @malept in [jdx#8544](jdx#8544) ### 🐛 Bug Fixes - **(aqua)** expose main binary when files field is empty and symlink_bins is enabled by @AlexanderTheGrey in [jdx#8550](jdx#8550) - **(env)** redact secrets in `mise set` listing and task-specific env by @jdx in [jdx#8583](jdx#8583) - **(prepare)** install config tools before running prepare steps by @jdx in [jdx#8582](jdx#8582) - **(task)** allow ctrl-c to interrupt tool downloads during `mise run` by @jdx in [jdx#8571](jdx#8571) - **(tasks)** add file task header parser support for spaces around = by @roele in [jdx#8574](jdx#8574) ### 📚 Documentation - **(task)** add property description for interactive by @roele in [jdx#8562](jdx#8562) - add missing `</bold>` closing tag by @muzimuzhi in [jdx#8564](jdx#8564) - rebrand site with new chef logo and warm culinary palette by @jdx in [jdx#8587](jdx#8587) ### 📦️ Dependency Updates - update ghcr.io/jdx/mise:alpine docker digest to de4657e by @renovate[bot] in [jdx#8577](jdx#8577) - update ghcr.io/jdx/mise:copr docker digest to eef29a2 by @renovate[bot] in [jdx#8578](jdx#8578) - update ghcr.io/jdx/mise:rpm docker digest to 5a96587 by @renovate[bot] in [jdx#8580](jdx#8580) - update ghcr.io/jdx/mise:deb docker digest to 464cf7c by @renovate[bot] in [jdx#8579](jdx#8579) ### 📦 Registry - fix flatc version test mismatch by @jdx in [jdx#8588](jdx#8588) ### Chore - **(registry)** skip spark test-tool by @jdx in [jdx#8572](jdx#8572) ### New Contributors - @AlexanderTheGrey made their first contribution in [jdx#8550](jdx#8550) ## 📦 Aqua Registry Updates #### New Packages (6) - [`bahdotsh/mdterm`](https://github.com/bahdotsh/mdterm) - [`callumalpass/mdbase-lsp`](https://github.com/callumalpass/mdbase-lsp) - [`facebook/ktfmt`](https://github.com/facebook/ktfmt) - [`gurgeous/tennis`](https://github.com/gurgeous/tennis) - [`tektoncd/pipelines-as-code`](https://github.com/tektoncd/pipelines-as-code) - [`weedonandscott/trolley`](https://github.com/weedonandscott/trolley) #### Updated Packages (2) - [`apple/container`](https://github.com/apple/container) - [`cocogitto/cocogitto`](https://github.com/cocogitto/cocogitto)

Summary
InstallOptions::default()setsmissing_args_only: true, which only installs tools passed as CLI arguments — not tools from[tools]in config filesuvaren't available system-widemissing_args_only: falsein bothmise runandmise prepareso config tools are installed before prepare steps executeFixes #8567
Test plan
[tools] uv = "0.9.25"and a custom prepare step that runsuv pip install🤖 Generated with Claude Code
Note
Medium Risk
Changes tool auto-install behavior for
mise prepare/mise runand alters how prepare commands are executed (now via an inline shell), which could affect projects relying on previous argument parsing or auto-install settings.Overview
Ensures
mise prepareinstalls all configured[tools]before executing prepare rules by settingInstallOptions.missing_args_onlytofalse, preventing prepare steps from failing on clean machines.Aligns prepare command execution with task behavior by wrapping
PrepareCommand::from_stringin the configured inline shell (enabling pipes/redirects/&&) and updates--explainoutput to show the command description. Adds an e2e regression test (test_prepare_tool_install) that verifies tool installation occurs before the prepare step runs.Written by Cursor Bugbot for commit 288b0c4. This will update automatically on new commits. Configure here.