-
-
Notifications
You must be signed in to change notification settings - Fork 769
feat(lockfile): add options field for tool artifact identity #7092
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR adds an options field to the lockfile format to properly differentiate tool installations with different configuration options that affect which artifact is downloaded or compiled. This ensures lockfiles correctly track tools like ripgrep with options exe=rg,matching=musl separately from installations without these options, and supports core plugins with settings-based compiler conditionals.
Key Changes:
- Added
resolve_lockfile_options()method to Backend trait with implementations across 9 backends (ubi, cargo, github, go, pipx) and 4 core plugins (python, node, erlang, ruby) - Extended
LockfileToolstruct withoptionsfield and updated lockfile matching logic to require exact options match - Added
is_current()helper method toPlatformTargetfor determining if a target represents the current platform
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| src/backend/mod.rs | Adds resolve_lockfile_options() trait method with default empty implementation |
| src/backend/platform_target.rs | Adds is_current() helper method for platform comparison |
| src/backend/ubi.rs | Implements options tracking for exe, matching, matching_regex, provider |
| src/backend/cargo.rs | Implements options tracking for features, default-features, bin |
| src/backend/github.rs | Implements options tracking for asset_pattern, url, version_prefix |
| src/backend/go.rs | Implements options tracking for tags |
| src/backend/pipx.rs | Implements options tracking for extras, pipx_args, uvx_args, uvx |
| src/plugins/core/python.rs | Resolves compile and precompiled options from settings |
| src/plugins/core/node.rs | Resolves compile and flavor options from settings |
| src/plugins/core/erlang.rs | Resolves compile option from settings |
| src/plugins/core/ruby.rs | Resolves ruby_install option from settings |
| src/lockfile.rs | Adds options field to LockfileTool, updates parsing/serialization/matching logic |
| src/toolset/tool_request.rs | Updates lockfile_resolve to pass options to get_locked_version |
| src/cli/args/backend_arg.rs | Updates backend discovery to use empty options map |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| .find(|v| { | ||
| // Version prefix matching | ||
| let version_matches = prefix == "latest" || v.version.starts_with(prefix); | ||
| // Options must match exactly | ||
| let options_match = &v.options == request_options; | ||
| version_matches && options_match | ||
| }) |
Copilot
AI
Nov 27, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The version matching logic using starts_with can cause issues when you have versions like '3.1' and '3.12'. A prefix of '3.1' would incorrectly match '3.12'. Consider using semantic version comparison or ensuring the prefix is followed by a version separator (e.g., '.', '-', or end of string).
| /// For the current platform: resolves from Settings and ToolRequest options | ||
| /// For other platforms (cross-platform mise lock): uses sensible defaults |
Copilot
AI
Nov 27, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The documentation should clarify what 'sensible defaults' means for cross-platform scenarios. It would be helpful to explicitly state what the expected behavior is when target.is_current() is false, such as whether it should use minimal/conservative options or platform-specific defaults.
| /// For the current platform: resolves from Settings and ToolRequest options | |
| /// For other platforms (cross-platform mise lock): uses sensible defaults | |
| /// For the current platform (`target.is_current()` is true): resolves from Settings and ToolRequest options. | |
| /// For other platforms (cross-platform mise lock, where `target.is_current()` is false): the default implementation returns an empty set of options (i.e., minimal/conservative options). | |
| /// Backends may override this method to provide platform-specific defaults if certain options are required for artifact resolution on non-host platforms. |
de66491 to
69ec1f5
Compare
69ec1f5 to
3746bb2
Compare
3746bb2 to
98cccee
Compare
8eda47e to
785824f
Compare
785824f to
6a0c56b
Compare
Add an `options` field to `LockfileTool` to properly account for tool options that affect which artifact is downloaded or compiled. This ensures lockfiles correctly differentiate between installations with different options (e.g., `exe=rg,matching=musl` for ripgrep). Key changes: - Add `resolve_lockfile_options()` method to Backend trait - Add `options` field to `LockfileTool` (only serialized when non-empty) - Update `get_locked_version()` to require exact options match - Implement for simple backends (ubi, cargo, github, go, pipx) - Implement for core plugins (python, node, erlang, ruby) with settings-based compiler conditionals support The core plugins resolve settings like `python.compile`, `node.flavor`, etc. at lockfile generation time. For cross-platform lockfile generation, defaults are used for non-current platforms. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
When using a lockfile URL to install an aqua package, the version was being inferred incorrectly. The code only checked for "v" prefix (like "v1.8.1") but didn't account for the package's version_prefix (like "jq-" for jq). This caused checksum verification to fail because it tried to look up the GitHub release using the wrong tag (e.g., "1.8.1" instead of "jq-1.8.1"). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
93060a7 to
ba2f042
Compare
3b663f2 to
1f52764
Compare
Fix clippy type_complexity warning by extracting the 6-tuple type into a named LockTaskResult type alias. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Hyperfine Performance
|
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2025.11.10 x -- echo |
20.3 ± 0.5 | 19.3 | 24.0 | 1.00 |
mise x -- echo |
20.9 ± 0.6 | 19.4 | 22.7 | 1.03 ± 0.04 |
mise env
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2025.11.10 env |
19.7 ± 0.7 | 18.8 | 28.6 | 1.00 |
mise env |
20.4 ± 0.6 | 19.2 | 25.3 | 1.04 ± 0.05 |
mise hook-env
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2025.11.10 hook-env |
19.7 ± 0.4 | 18.6 | 20.9 | 1.00 |
mise hook-env |
20.5 ± 0.7 | 19.2 | 24.1 | 1.04 ± 0.04 |
mise ls
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2025.11.10 ls |
16.8 ± 0.4 | 16.0 | 18.3 | 1.00 |
mise ls |
17.8 ± 0.5 | 16.3 | 19.3 | 1.05 ± 0.04 |
xtasks/test/perf
| Command | mise-2025.11.10 | mise | Variance |
|---|---|---|---|
| install (cached) | 107ms | 108ms | +0% |
| ls (cached) | 65ms | 66ms | -1% |
| bin-paths (cached) | 72ms | 72ms | +0% |
| task-ls (cached) | 423ms | 433ms | -2% |
## Summary Updates the lockfile documentation (`docs/dev-tools/mise-lock.md`) to reflect the recent changes since v2025.11.10: - **#7091** - Cross-platform lockfile generation - **#7093** - Always use TOML array format `[[tools.name]]` - **#7092** - Added `options` field for backend-specific artifact identity - **#7098** - Added `locked` setting for strict lockfile mode - **#7099** - Added `env` field and `mise.local.lock` support ### Changes - Update file format examples to use array syntax `[[tools.name]]` - Add documentation for new fields: `options`, `env` - Add **Environment-Specific Versions** section (env field, MISE_ENV workflow) - Add **Local Lockfiles** section (mise.local.lock, --local flag) - Add **Strict Lockfile Mode** section (locked setting) - Remove outdated **Legacy Format Migration** and **Benefits of the New Format** sections ## Test plan - [ ] Verify docs build correctly with `mise run docs` - [ ] Review documentation renders correctly on the site 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Refreshes `mise.lock` docs to use `[[tools.name]]` array syntax, add `options`/`env`, document environment-specific and local lockfiles, and introduce strict `locked` mode while removing obsolete sections. > > - **Docs (lockfile)** > - **File format**: > - Switch examples to `[[tools.name]]` array syntax > - Add fields: `options`, `env`; clarify `platforms` metadata and platform key formats > - **Environment-specific versions**: > - Document `MISE_ENV` workflow and resolution priority; show `mise.test.toml` example > - **Local lockfiles**: > - Explain `mise.local.toml` → `mise.local.lock`, `--local` usage and commands > - **Strict lockfile mode**: > - Add `locked` setting (`mise settings locked=true`, `MISE_LOCKED=1`) and `mise lock` URL pre-resolution workflow > - **Cleanup**: > - Remove Legacy Format Migration and Benefits sections > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit e6fe67f. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> Co-authored-by: Claude <[email protected]>
### 🚀 Features - **(backend)** add filter_bins option to github/gitlab backends by @risu729 in [#7105](#7105) - **(ci)** auto-close PRs from non-maintainers by @jdx in [#7108](#7108) - **(conda)** add conda backend for installing packages from conda-forge by @jdx in [#7139](#7139) - **(github)** add rename_exe option and switch elm, opam, yt-dlp from ubi by @jdx in [#7140](#7140) - **(install)** add --locked flag for strict lockfile mode by @jdx in [#7098](#7098) - **(lock)** implement cross-platform lockfile generation by @jdx in [#7091](#7091) - **(lockfile)** add options field for tool artifact identity by @jdx in [#7092](#7092) - **(lockfile)** add env field and local lockfile support by @jdx in [#7099](#7099) - **(lockfile)** add URL support for deno, go, and zig backends by @jdx in [#7112](#7112) - **(lockfile)** add URL support for vfox backend by @jdx in [#7114](#7114) - **(lockfile)** add multi-platform checksums without downloading tarballs by @jdx in [#7113](#7113) ### 🐛 Bug Fixes - **(backend)** allow platform-specific strip_components by @risu729 in [#7106](#7106) - **(backend)** prefer path root for bin path if it contains an executable by @risu729 in [#7151](#7151) - **(bash)** avoid deactivate error on (no)unset PROMPT_COMMAND by @scop in [#7096](#7096) - **(ci)** use updatedAt instead of createdAt for stale PR detection by @jdx in [#7109](#7109) - **(github)** search subdirectories for executables in discover_bin_paths by @jdx in [#7138](#7138) - **(lockfile)** combine api_url with asset_pattern for GitHub release URLs by @jdx in [#7111](#7111) ### 🚜 Refactor - **(lock)** simplify lockfile to always use array format by @jdx in [#7093](#7093) - **(lockfile)** use compact inline table format by @jdx in [#7141](#7141) ### 📚 Documentation - **(gitlab)** document rename_exe option also for gitlab backend by @risu729 in [#7149](#7149) - **(lockfile)** update documentation for recent lockfile changes by @jdx in [#7107](#7107) - **(node)** use config_root in _.path for pnpm example by @risu729 in [#7146](#7146) - **(registry)** add github/gitlab backends to the preferred backends list by @risu729 in [#7148](#7148) - **(registry)** add url mappings for all backends by @risu729 in [#7147](#7147) ### 📦️ Dependency Updates - update docker/metadata-action digest to c299e40 by @renovate[bot] in [#7101](#7101) - update ghcr.io/jdx/mise:alpine docker digest to 693c5f6 by @renovate[bot] in [#7102](#7102) - update ghcr.io/jdx/mise:deb docker digest to 9985cab by @renovate[bot] in [#7104](#7104) - update ghcr.io/jdx/mise:copr docker digest to 564d8e1 by @renovate[bot] in [#7103](#7103) - update rust crate ubi to 0.8.4 by @risu729 in [#7154](#7154) ### 📦 Registry - add aqua backend as primary for e1s by @jdx in [#7115](#7115) - add gem backend for bashly by @jdx in [6af6607](6af6607) - switch 1password from asdf to vfox backend by @jdx in [#7116](#7116) - add vfox backend for bfs by @jdx in [#7126](#7126) - add github backend for btrace by @jdx in [#7129](#7129) - add github backend for cf by @jdx in [#7131](#7131) - add vfox backend for bpkg by @jdx in [#7130](#7130) - switch apollo-ios from asdf to github backend by @jdx in [#7118](#7118) - add vfox backend for chromedriver by @jdx in [#7134](#7134) - switch superhtml, vespa-cli, xcsift from ubi to github backend by @jdx in [#7137](#7137) - add vfox backend for clickhouse by @jdx in [#7136](#7136) - switch chicken to vfox plugin by @jdx in [#7135](#7135) - switch chezscheme from asdf to vfox backend by @jdx in [#7132](#7132) - add vfox backend for carthage by @jdx in [#7133](#7133) - switch azure-functions-core-tools from asdf to vfox backend by @jdx in [#7128](#7128) - switch aapt2 to vfox backend by @jdx in [#7117](#7117) - switch ant to vfox backend by @jdx in [#7119](#7119) - switch asciidoctorj from asdf to vfox backend by @jdx in [#7121](#7121) - switch awscli-local to pipx backend by @jdx in [#7120](#7120) - add omnictl by @risu729 in [#7145](#7145) - remove pnpm asdf plugin from fallback by @risu729 in [#7143](#7143) - switch tanzu to github backend by @jdx in [#7124](#7124) - switch android-sdk to vfox plugin by @jdx in [#7127](#7127) - add vfox backend for ag (The Silver Searcher) by @jdx in [#7122](#7122) ### Chore - **(registry)** ignore deleted tools in test-tool workflow by @risu729 in [#7081](#7081) - **(release)** show registry section last in changelog by @jdx in [#7156](#7156) - update mise.lock with checksums by @jdx in [71e9123](71e9123) - disable cancel-in-progress for test workflow on main branch by @risu729 in [#7152](#7152) ## 📦 Aqua Registry Updates #### Updated Packages (1) - [`orf/gping`](https://github.com/orf/gping)
Summary
optionsfield toLockfileToolto properly account for tool options that affect which artifact is downloaded or compiledexe=rg,matching=muslfor ripgrep)Note: This PR is based on #7091 (cross-platform lockfile support)
Key Changes
Core Infrastructure:
resolve_lockfile_options()method to Backend trait with default empty implementationoptionsfield toLockfileToolstruct (only serialized when non-empty viaskip_serializing_if)get_locked_version()to require exact options matchis_current()method toPlatformTargetmise lockcall toxtasks/release-plzscriptSimple Backend Implementations:
exe,matching,matching_regex,providerfeatures,default-features,binasset_pattern,url,version_prefixtagsextras,pipx_args,uvx_args,uvxCore Plugin Implementations:
compile,precompiled_arch,precompiled_os,precompiled_flavorcompile=falsecompile,flavorcompile=falsecompilecompile=falseruby_installruby_install=falseNew Lockfile Format
Test plan
mise locksuccessfully in repo🤖 Generated with Claude Code
Note
Add
optionsto lockfile and implement backend/plugin hooks to resolve and persist artifacts based on option-sensitive identities; update CLI lock flow and tests.optionstoLockfileTool; serialize only when non-empty; parse from TOML.options; merge logic updated accordingly.Backend::resolve_lockfile_options(default empty) andPlatformTarget::is_current().ToolRequest.lockfile_resolvepasses resolved options;get_locked_backendadded for discovery.github,ubi,cargo,go,pipximplementresolve_lockfile_options(e.g.,asset_pattern/url/version_prefix,exe/matching/provider,features/default-features/bin,tags,extras/pipx_args/uvx[_args]).aquaimproves version-prefix detection from existing URLs.python,node,erlang,rubyreturn settings-derived options (e.g.,compile,flavor,ruby_install, precompiled selectors) for current platform only.mise lockresolves per-platform URLs and stores alongside resolvedoptions.backend_argprefers backend from lockfile when present.xtasks/release-plznow runsmise lockand stagesmise.locket al.mise.lockrefreshed with explicit platform assets.Written by Cursor Bugbot for commit d7e4801. This will update automatically on new commits. Configure here.