fix(lock): scope targets to active project root#9319
Conversation
Greptile SummaryThis PR scopes The core logic is sound: Confidence Score: 5/5Safe to merge — no logic bugs found; intentional breaking changes are well-tested and documented. No P0 or P1 issues. The scoping logic is correct: config_root::config_root canonicalises all config layout variants (.config/mise.toml, mise.local.toml, etc.) to the same project root, making the equality filter in config_paths_in_lock_scope reliable. The --global exclusivity change, compute_config_bumps_for_paths refactor, and all generated-doc updates are consistent. Prior review comments have been addressed. E2E tests cover nested projects, monorepos, global-only scope, and scoped version bumps. No files require special attention. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A["mise lock [tool@ver]"] --> B{--global?}
B -- Yes --> C["config_paths_in_lock_scope\n→ global + system config paths only"]
B -- No --> D["target_lock_scope_root\n(config.project_root or first local mise.toml root)"]
D --> E{project root found?}
E -- No --> F["empty set\n→ 'No tools configured to lock'"]
E -- Yes --> G["filter config_files where\nproject_root|config_root == target_root\nexclude global configs"]
C --> H["get_lockfile_targets\n(skip non-mise-toml)"]
G --> H
H --> I["For each lockfile target:\nget_tools_to_lock → process_tools → write lockfile"]
I --> J{specific tool@ver requested?}
J -- Yes --> K["compute_config_bumps_for_paths\n(scoped_config_paths)\nskips global configs"]
J -- No --> L["done"]
K --> M["apply_config_bumps or dry-run display"]
M --> L
Reviews (6): Last reviewed commit: "[autofix.ci] apply automated fixes" | Re-trigger Greptile |
There was a problem hiding this comment.
Code Review
This pull request implements project-root scoping for the mise lock command, restricting lock operations and version bumps to the current project's configuration files unless the --global flag is used. It introduces logic to identify the target lock scope root and updates the lockfile target collection and configuration bump processes to respect these boundaries. A new E2E test suite is included to validate the scoping behavior. Feedback was provided regarding the use of canonicalized paths for root comparisons and potential performance optimizations when collecting configuration paths.
843f1f5 to
f0fa9fa
Compare
f0fa9fa to
a2d35a8
Compare
a2d35a8 to
cc50fbd
Compare
### 🚀 Features - **(aqua)** support registry libc variants by @jdx in [#9652](#9652) - **(bin-paths)** add executable names output by @risu729 in [#9617](#9617) ### 🐛 Bug Fixes - **(aqua)** preserve configured file extensions by @risu729 in [#9611](#9611) - **(aqua)** support registry file links by @risu729 in [#9610](#9610) - **(backend)** reject bare package backend names by @risu729 in [#9608](#9608) - **(backend)** apply inline tool option overrides by @risu729 in [#9306](#9306) - **(backend)** skip versions host for local tool opts by @risu729 in [#9568](#9568) - **(github)** chmod explicit archive bin by @risu729 in [#9609](#9609) - **(install)** skip remote-versions refresh in prefer-offline mode by @jdx in [#9627](#9627) - **(lock)** scope targets to active project root by @risu729 in [#9319](#9319) - **(lockfile)** respect existing platforms during auto-lock by @jdx in [#9621](#9621) - **(pipx)** filter yanked pypi releases by @risu729 in [#9607](#9607) - **(pipx)** declare python as a backend dependency by @jdx in [#9678](#9678) - **(schema)** update refs to $defs in mise-registry-tool.json by @risu729 in [#9671](#9671) - **(task)** terminate parallel siblings on failure via process groups by @jdx in [#9655](#9655) - **(task)** stable MISE_PROJECT_ROOT for monorepo tasks, add MISE_MONOREPO_ROOT by @jdx in [#9657](#9657) - **(trust)** run enter hooks after trusting config by @risu729 in [#9634](#9634) - **(ui)** stop clearing screen for prompts by @jdx in [#9619](#9619) - use /bin/cp on macos by @pdehlke in [#9656](#9656) ### 🚜 Refactor - **(aqua)** store aqua var defaults as strings by @risu729 in [#9645](#9645) - **(config)** support structured TOML values in registry backend options by @risu729 in [#9584](#9584) - **(deps)** remove serde_derive dependency by @risu729 in [#9670](#9670) - **(deps)** remove anyhow dependency by @risu729 in [#9661](#9661) - **(deps)** use std::sync::LazyLock instead of once_cell::Lazy by @risu729 in [#9668](#9668) - **(schema)** generate task schema from mise schema by @risu729 in [#9581](#9581) - **(schema)** reuse task props with unevaluatedProperties by @risu729 in [#9582](#9582) - **(schema)** reuse registry common types by @risu729 in [#9648](#9648) - **(schema)** reuse plugin script config by @risu729 in [#9647](#9647) - **(schema)** use $defs in schema files by @risu729 in [#9646](#9646) ### 📚 Documentation - **(node)** add tips for enabling node idiomatic by @fu050409 in [#9675](#9675) ### 🧪 Testing - **(cli)** remove nondeterministic tool depends assertion by @risu729 in [#9633](#9633) - **(e2e)** pin uv to 0.11.8 around astral-sh/uv#19278 by @jdx in [#9618](#9618) - **(e2e)** wait for docker env cleanup by @risu729 in [#9631](#9631) - **(zig)** use official zig instead of mach mirror by @jdx in [#9659](#9659) ### 📦️ Dependency Updates - fall through to hash check when providers have no outputs by @jdx in [#9622](#9622) - bump Cargo.lock by @jdx in [#9625](#9625) ### 📦 Registry - remove registry depends by @risu729 in [#9571](#9571) - add code-review-graph (pipx:code-review-graph) by @chautruonglong in [#9673](#9673) ### Chore - **(ci)** split large registry test-tool changes by @risu729 in [#9628](#9628) - **(ci)** make perf script robust to runner noise by @jdx in [#9635](#9635) - **(ci)** skip hyperfine comments without permission by @risu729 in [#9629](#9629) ### New Contributors - @chautruonglong made their first contribution in [#9673](#9673) - @pdehlke made their first contribution in [#9656](#9656) ## 📦 Aqua Registry Updates ### New Packages (5) - [`anthropics/anthropic-cli`](https://github.com/anthropics/anthropic-cli) - [`crates.io/wasmi_cli`](https://github.com/wasmi-labs/wasmi) - [`openclaw/gogcli`](https://github.com/openclaw/gogcli) - `racket-lang.org/racket-minimal` - [`runs-on/cli`](https://github.com/runs-on/cli) ### Updated Packages (13) - [`UpCloudLtd/upcloud-cli`](https://github.com/UpCloudLtd/upcloud-cli) - [`aristocratos/btop`](https://github.com/aristocratos/btop) - [`dprint/dprint`](https://github.com/dprint/dprint) - [`j178/prek`](https://github.com/j178/prek) - [`jdx/hk`](https://github.com/jdx/hk) - [`jdx/mise`](https://github.com/jdx/mise) - [`jdx/usage`](https://github.com/jdx/usage) - [`jreleaser/jreleaser`](https://github.com/jreleaser/jreleaser) - [`jreleaser/jreleaser/standalone`](https://github.com/jreleaser/jreleaser) - [`pnpm/pnpm`](https://github.com/pnpm/pnpm) - [`suzuki-shunsuke/cmdx`](https://github.com/suzuki-shunsuke/cmdx) - [`suzuki-shunsuke/ghir`](https://github.com/suzuki-shunsuke/ghir) - [`twpayne/chezmoi`](https://github.com/twpayne/chezmoi)
Why
mise lockcurrently derives its lockfile targets from every loadedmise.toml-style config. That is too broad when the command is run from a nested project: the loaded hierarchy can include both a parent config and the current project's config, so a focused lock operation from the child can still update or prune the parent's lockfile.That behavior is especially awkward for automation such as Renovate. Those tools usually operate on a specific config file or subproject and expect
mise lock <tool>to refresh only the lockfiles owned by that target. If parent configs stay in scope, a narrow update can produce unrelated lockfile churn or inspect parent config entries during the explicit-version bump pass.Changes
mise.toml-style config files that belong to the active project config root.mise.toml,mise.local.toml,mise.<env>.toml,.config/mise.toml, and related layouts still route to their normal lockfiles.mise lock tool@versioncannot fall through to a parent config after lockfile targets are narrowed.--globalas an exclusive global/system scope, not an additive mode, and update the CLI help/generated docs to describe that behavior.Monorepos
Monorepo config roots remain separate lockfile ownership boundaries. Running
mise lockfrom a monorepo package updates only that package's active config root lockfiles; shared tools defined in the monorepo root remain owned by the monorepo root lockfile and should be refreshed by runningmise lockat the root.Likewise, running
mise lockat the monorepo root does not scan[monorepo].config_rootsand update child package lockfiles. That keeps monorepo lock updates focused on the config root where the command is invoked and avoids unrelated package lockfile churn.Validation
cargo fmt --checkgit diff --checkshellcheck -x e2e/cli/test_lock_project_root_scopeshfmt -d e2e/cli/test_lock_project_root_scopecargo test toolset::outdated_infomise run test:e2e e2e/cli/test_lock_project_root_scope e2e/cli/test_lock_globalThis PR description was generated by an AI coding assistant.