Skip to content

fix(lock): lock idiomatic version file tools#10309

Merged
jdx merged 4 commits into
mainfrom
codex/fix-idiomatic-lockfile
Jun 11, 2026
Merged

fix(lock): lock idiomatic version file tools#10309
jdx merged 4 commits into
mainfrom
codex/fix-idiomatic-lockfile

Conversation

@jdx

@jdx jdx commented Jun 11, 2026

Copy link
Copy Markdown
Owner

Summary

Fixes an inconsistency where tools resolved from idiomatic version files, such as .node-version, were visible in the active toolset but were not written to mise.lock. A later mise install --locked would then reject the same tool as missing from the lockfile.

Root Cause

Lockfile update paths mapped tool sources by treating any source path like a mise config file. For idiomatic version files, that produced a sibling lockfile path based on .node-version or .python-version, which did not match the actual project mise.lock target.

Changes

  • Add shared source-to-lockfile mapping for tool sources.
  • Map idiomatic version files to the nearest active base mise config root that contains them.
  • Use that mapping from both explicit mise lock and install-time lockfile update/autolock flows.
  • Add an e2e regression covering mise lock, mise install, and mise install --locked --dry-run for idiomatic version file tools.

Validation

  • cargo fmt --check
  • cargo check
  • mise run test:e2e e2e/lockfile/test_lockfile_idiomatic_version_file

Note

Medium Risk
Changes lockfile routing for install and mise lock across multiple code paths; wrong mapping could omit tools or write to the wrong lockfile, though behavior for non-idiomatic sources is largely preserved.

Overview
Fixes tools from idiomatic version files (e.g. .node-version) showing in the active toolset but not landing in the project mise.lock, which broke mise install --locked.

Adds lockfile_path_for_tool_source, which maps mise.toml sources as before and attaches idiomatic version files to the nearest enclosing base mise config root instead of a bogus sibling lock path. mise lock, update_lockfiles, snapshot_pre_install_platforms, and auto_lock_new_versions all use this mapping; install-time autolock now takes Config so idiomatic sources participate. get_tools_to_lock also includes idiomatic configs in its second pass and resolves overridden idiomatic requests (not only latest), while skipping path-backed sources like .tool-versions from arbitrary project locks.

New e2e test_lockfile_idiomatic_version_file covers mise lock, install updating the lock, and locked dry-run for node and dummy tools.

Reviewed by Cursor Bugbot for commit 4af9d2e. Bugbot is set up for automated code reviews on this repo. Configure here.

Summary by CodeRabbit

  • Tests

    • Added an end-to-end test covering idiomatic version-file support, verifying lockfile population, platform-specific entries, dry-run install messages, and install behavior for multiple tool scenarios.
  • Refactor

    • Tools are now mapped to their correct target lockfiles so updates go to the right lockfile.
    • Pre-install platform snapshots and grouping of newly discovered versions were improved to ensure correct propagation into each lockfile.

@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Maps tool sources (mise.toml and idiomatic version files) to target lockfiles via a new helper, refactors lockfile update/snapshot/auto-lock flows to group by that mapping, updates CLI/config callers to pass Config, and adds e2e tests validating node and dummy idiomatic-file behaviors.

Changes

Idiomatic Version File Lockfile Support

Layer / File(s) Summary
Lockfile source mapping helper
src/lockfile.rs
New lockfile_path_for_tool_source(config, source) determines a tool source's target lockfile: mise.toml sources use existing config logic; idiomatic version files choose the nearest active config root and return a lockfile path plus locality.
Lockfile update & grouping
src/lockfile.rs
update_lockfiles, snapshot_pre_install_platforms, and auto_lock_new_versions now group ToolVersion items by the computed tool-source lockfile path and apply updates only to matching lockfiles; snapshot keys use the computed lockfile path.
Caller integration
src/cli/lock.rs, src/config/mod.rs
Lock::get_tools_to_lock and rebuild_shims_and_runtime_symlinks now derive source lockfile via the helper and pass the active Config into lockfile snapshot/auto-lock calls.
E2E test validation
e2e/lockfile/test_lockfile_idiomatic_version_file
Two Bash scenarios exercise idiomatic version file behavior: .node-version with mise lock and .dummy-version with mise install dummy, asserting lockfile entries, backend strings, and --dry-run --locked behavior.

Estimated Code Review Effort

🎯 4 (Complex) | ⏱️ ~45 minutes

🐰 I nibble on a .node-version bright,
I stamp each tool its lockfile right,
From dummy hops to backend strings I sing,
A tiny rabbit, locking everything! 🥕🔐

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'fix(lock): lock idiomatic version file tools' directly and concisely summarizes the main change: fixing the locking of tools resolved from idiomatic version files, which is the core problem addressed across all modified files.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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


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

Comment thread src/cli/lock.rs
@greptile-apps

greptile-apps Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Fixes tools sourced from idiomatic version files (e.g. .node-version) being visible in the active toolset but silently omitted from mise.lock, which caused mise install --locked to reject them as unlocked.

  • New lockfile_path_for_tool_source: centralized source→lockfile mapping that routes IdiomaticVersionFile sources to the deepest enclosing mise.toml's lockfile (via max_by_key on root depth + base-config preference), replacing the previous naive lockfile_path_for_config(source_path) calls that produced sibling lock paths next to the version file.
  • update_lockfiles / snapshot_pre_install_platforms / auto_lock_new_versions: the old is_mise_toml() gate and config-path iteration are replaced by the unified mapping function, so idiomatic version file tools now flow into the correct lockfile during both mise lock and install-time update paths.
  • mise lock second pass: extended to walk idiomatic version file sources and resolve all overridden requests (not just latest) so tools like dummy@1.1.0 from .dummy-version land in the lockfile even when a higher-priority mise.toml entry overrides them.

Confidence Score: 5/5

Safe to merge — the change is narrowly scoped to idiomatic version file sources and every affected code path has a matching test scenario.

The new lockfile_path_for_tool_source function correctly routes idiomatic version files to their enclosing mise.toml lockfile using a depth + base-config tie-breaker. All three modified flows consistently use the same mapping, and the e2e test covers the lock, install, and locked-dry-run paths end-to-end.

No files require special attention.

Important Files Changed

Filename Overview
src/lockfile.rs Adds lockfile_path_for_tool_source to correctly map idiomatic version files to their enclosing mise.toml lockfile; refactors update_lockfiles, snapshot_pre_install_platforms, and auto_lock_new_versions to use it — removing the old is_mise_toml guard and config-path-only lookup.
src/cli/lock.rs First-pass tool collection now uses lockfile_path_for_tool_source instead of raw lockfile_path_for_config; second pass extended to include idiomatic version file sources that map to the target lockfile; should_resolve_overridden broadened to cover all overridden requests from idiomatic files (not just latest).
src/config/mod.rs Threads config reference into snapshot_pre_install_platforms and auto_lock_new_versions call sites to support the new source-mapping logic.
e2e/lockfile/test_lockfile_idiomatic_version_file New e2e test covering three scenarios: mise lock for node via .node-version, dry-run lock with overridden dummy versions, and install-time lockfile update for dummy via .dummy-version; cleanup is present at the end of each scenario.

Reviews (4): Last reviewed commit: "fix(lock): simplify idiomatic lock guard" | Re-trigger Greptile

Comment thread e2e/lockfile/test_lockfile_idiomatic_version_file
@jdx jdx marked this pull request as ready for review June 11, 2026 18:46

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/cli/lock.rs (1)

548-551: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Recover overridden idiomatic-version-file requests here too.

This fallback only walks config_paths, but get_lockfile_targets() populates that list from mise.toml sources only. An idiomatic file like .node-version or .python-version that's shadowed by a higher-precedence config drops out of pass 1, and pass 2 never sees it, so an unfiltered mise lock can prune a still-configured entry from mise.lock.

Also applies to: 552-605

🤖 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 `@src/cli/lock.rs` around lines 548 - 551, The fallback loop over
config.config_files currently skips entries not in config_paths_set, which drops
idiomatic-version-file requests that were sourced from mise.toml shadowing;
update the condition inside the loop (the block that iterates
config.config_files in src/cli/lock.rs) to also accept entries that represent
idiomatic version files by checking the original lockfile targets or the config
file's source kind (e.g., if the entry's source is an IdiomaticVersionFile enum
variant or the path matches known idiomatic names like ".node-version" /
".python-version"); in short, change the guard from only
config_paths_set.contains(path) to allow paths present in config_paths_set OR
entries whose source/metadata marks them as idiomatic-version-file (or present
in the initial get_lockfile_targets() result), so pass 2 will recover those
overridden idiomatic requests instead of pruning them from mise.lock.
🤖 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.

Outside diff comments:
In `@src/cli/lock.rs`:
- Around line 548-551: The fallback loop over config.config_files currently
skips entries not in config_paths_set, which drops idiomatic-version-file
requests that were sourced from mise.toml shadowing; update the condition inside
the loop (the block that iterates config.config_files in src/cli/lock.rs) to
also accept entries that represent idiomatic version files by checking the
original lockfile targets or the config file's source kind (e.g., if the entry's
source is an IdiomaticVersionFile enum variant or the path matches known
idiomatic names like ".node-version" / ".python-version"); in short, change the
guard from only config_paths_set.contains(path) to allow paths present in
config_paths_set OR entries whose source/metadata marks them as
idiomatic-version-file (or present in the initial get_lockfile_targets()
result), so pass 2 will recover those overridden idiomatic requests instead of
pruning them from mise.lock.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 24729a01-4abb-4906-aded-f73c8d6a8c1b

📥 Commits

Reviewing files that changed from the base of the PR and between fa0ec9d and 765a06e.

📒 Files selected for processing (4)
  • e2e/lockfile/test_lockfile_idiomatic_version_file
  • src/cli/lock.rs
  • src/config/mod.rs
  • src/lockfile.rs

@github-actions

github-actions Bot commented Jun 11, 2026

Copy link
Copy Markdown

Hyperfine Performance

mise x -- echo

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.6.2 x -- echo 19.8 ± 0.9 17.9 25.0 1.00
mise x -- echo 21.0 ± 2.9 18.5 39.7 1.06 ± 0.15

mise env

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.6.2 env 19.3 ± 0.9 17.3 23.8 1.00
mise env 19.9 ± 1.0 17.8 23.9 1.03 ± 0.07

mise hook-env

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.6.2 hook-env 19.9 ± 0.9 18.2 24.1 1.00
mise hook-env 20.6 ± 1.0 18.5 24.5 1.03 ± 0.07

mise ls

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.6.2 ls 16.5 ± 0.8 14.6 20.7 1.00
mise ls 16.8 ± 0.9 15.0 22.5 1.02 ± 0.07

xtasks/test/perf

Command mise-2026.6.2 mise Variance
install (cached) 141ms 142ms +0%
ls (cached) 61ms 61ms +0%
bin-paths (cached) 66ms 66ms +0%
task-ls (cached) 130ms 130ms +0%

@jdx jdx enabled auto-merge (squash) June 11, 2026 19:15

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 4af9d2e. Configure here.

Comment thread src/lockfile.rs
})
})
.max_by_key(|(root_depth, is_base, _)| (*root_depth, *is_base))
.map(|(_, _, lockfile)| lockfile),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Ambiguous idiomatic lockfile mapping

Medium Severity

When several base mise.toml configs share the same project_root, lockfile_path_for_tool_source picks the target lockfile via max_by_key on (root_depth, is_base) over forward config_files iteration. Ties (e.g. root mise.toml vs .mise/config.toml) keep the first match in map order, not the highest-precedence config used elsewhere, so idiomatic tools can land in the wrong mise.lock.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 4af9d2e. Configure here.

@jdx jdx merged commit 90582ff into main Jun 11, 2026
34 checks passed
@jdx jdx deleted the codex/fix-idiomatic-lockfile branch June 11, 2026 20:06
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