Skip to content

fix(lock): scope targets to active project root#9319

Merged
jdx merged 2 commits intojdx:mainfrom
risu729:codex/scope-lock-config-targets
May 5, 2026
Merged

fix(lock): scope targets to active project root#9319
jdx merged 2 commits intojdx:mainfrom
risu729:codex/scope-lock-config-targets

Conversation

@risu729
Copy link
Copy Markdown
Contributor

@risu729 risu729 commented Apr 23, 2026

Why

mise lock currently derives its lockfile targets from every loaded mise.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

  • Compute one bounded config path set before collecting lockfile targets.
  • By default, keep only mise.toml-style config files that belong to the active project config root.
  • Keep supported config variants under that same root together, so mise.toml, mise.local.toml, mise.<env>.toml, .config/mise.toml, and related layouts still route to their normal lockfiles.
  • Exclude parent project configs from the target set when running from a child project.
  • Reuse the same scoped config path set for explicit-version config bumps, so mise lock tool@version cannot fall through to a parent config after lockfile targets are narrowed.
  • Treat --global as 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 lock from 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 running mise lock at the root.

Likewise, running mise lock at the monorepo root does not scan [monorepo].config_roots and 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 --check
  • git diff --check
  • shellcheck -x e2e/cli/test_lock_project_root_scope
  • shfmt -d e2e/cli/test_lock_project_root_scope
  • cargo test toolset::outdated_info
  • mise run test:e2e e2e/cli/test_lock_project_root_scope e2e/cli/test_lock_global

This PR description was generated by an AI coding assistant.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 23, 2026

Greptile Summary

This PR scopes mise lock to the active project's config root so that running it from a nested project no longer touches parent lockfiles. It also changes --global from additive (project + global) to exclusive (global + system only), and applies the same scoping to version-bump config updates (compute_config_bumps_for_paths).

The core logic is sound: config_paths_in_lock_scope correctly uses config_root::config_root to resolve .config/mise.toml and related layouts back to the project root, and target_lock_scope_root safely falls back to BTreeMap-ordered iteration (where deeper paths sort first, giving the most-local config) when config.project_root is unset. The --global behavior change and help-text updates are consistent across lock.rs, generated docs, man page, and Fig completions. Prior review comments about --global semantics have been addressed in this revision.

Confidence Score: 5/5

Safe 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

Filename Overview
src/cli/lock.rs Core lock command updated: adds config_paths_in_lock_scope / target_lock_scope_root helpers and passes scoped paths to get_lockfile_targets; --global is now exclusive (not additive). Help text updated throughout. Logic is correct.
src/toolset/outdated_info.rs Clean refactor: compute_config_bumps now delegates to new compute_config_bumps_for_paths with a full-path set; callers in upgrade.rs are unaffected. Scoped variant used by lock.rs prevents parent-config version bumps.
e2e/cli/test_lock_project_root_scope New e2e test covering nested project scope, monorepo scope, global-only scope, and scoped version bumps. Comprehensive and well-structured.
e2e/cli/test_lock_global Updated to assert that --global is now exclusive (system lockfile created, project lockfile absent). System config fixture added.
docs/cli/lock.md Help text updated to reflect exclusive --global semantics and active project config root scoping.

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
Loading

Reviews (6): Last reviewed commit: "[autofix.ci] apply automated fixes" | Re-trigger Greptile

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

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.

Comment thread src/cli/lock.rs
Comment thread src/toolset/outdated_info.rs
@risu729 risu729 force-pushed the codex/scope-lock-config-targets branch 2 times, most recently from 843f1f5 to f0fa9fa Compare April 24, 2026 01:11
@risu729 risu729 force-pushed the codex/scope-lock-config-targets branch from f0fa9fa to a2d35a8 Compare May 4, 2026 05:12
@risu729 risu729 force-pushed the codex/scope-lock-config-targets branch from a2d35a8 to cc50fbd Compare May 4, 2026 05:19
@risu729 risu729 marked this pull request as ready for review May 4, 2026 07:40
@jdx jdx merged commit e8fa8a6 into jdx:main May 5, 2026
35 checks passed
@risu729 risu729 deleted the codex/scope-lock-config-targets branch May 5, 2026 17:06
mise-en-dev added a commit that referenced this pull request May 7, 2026
### 🚀 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)
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.

2 participants