Skip to content

Conversation

@jdx
Copy link
Owner

@jdx jdx commented Nov 27, 2025

Summary

  • Adds 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)
  • Supports core plugins with settings-based compiler conditionals (python.compile, node.flavor, etc.)

Note: This PR is based on #7091 (cross-platform lockfile support)

Key Changes

Core Infrastructure:

  • Add resolve_lockfile_options() method to Backend trait with default empty implementation
  • Add options field to LockfileTool struct (only serialized when non-empty via skip_serializing_if)
  • Update get_locked_version() to require exact options match
  • Update merge logic to match on version AND options
  • Add is_current() method to PlatformTarget
  • Add mise lock call to xtasks/release-plz script

Simple Backend Implementations:

Backend Options tracked
ubi exe, matching, matching_regex, provider
cargo features, default-features, bin
github asset_pattern, url, version_prefix
go tags
pipx extras, pipx_args, uvx_args, uvx

Core Plugin Implementations:

Plugin Settings resolved Default for other platforms
python compile, precompiled_arch, precompiled_os, precompiled_flavor compile=false
node compile, flavor compile=false
erlang compile compile=false
ruby ruby_install ruby_install=false

New Lockfile Format

[[tools.ripgrep]]
version = "14.0.0"
backend = "ubi:BurntSushi/ripgrep"
options = { exe = "rg", matching = "musl" }

[tools.ripgrep.platforms.linux-x64]
checksum = "blake3:abc123"

Test plan

  • All existing tests pass
  • Added 4 new tests for options field parsing, serialization, and matching
  • Ran mise lock successfully in repo
  • Manual testing with different tool options

🤖 Generated with Claude Code


Note

Add options to lockfile and implement backend/plugin hooks to resolve and persist artifacts based on option-sensitive identities; update CLI lock flow and tests.

  • Lockfile/Core:
    • Add options to LockfileTool; serialize only when non-empty; parse from TOML.
    • Match lock entries by version AND exact options; merge logic updated accordingly.
    • Expose Backend::resolve_lockfile_options (default empty) and PlatformTarget::is_current().
    • ToolRequest.lockfile_resolve passes resolved options; get_locked_backend added for discovery.
  • Backends:
    • github, ubi, cargo, go, pipx implement resolve_lockfile_options (e.g., asset_pattern/url/version_prefix, exe/matching/provider, features/default-features/bin, tags, extras/pipx_args/uvx[_args]).
    • Minor: aqua improves version-prefix detection from existing URLs.
  • Core Plugins:
    • python, node, erlang, ruby return settings-derived options (e.g., compile, flavor, ruby_install, precompiled selectors) for current platform only.
  • CLI:
    • mise lock resolves per-platform URLs and stores alongside resolved options.
    • Defaults to common platforms + existing + current; parallelizes tasks; summarizes updates.
  • Tool resolution:
    • backend_arg prefers backend from lockfile when present.
  • Scripts/Lock:
    • xtasks/release-plz now runs mise lock and stages mise.lock et al.
    • mise.lock refreshed with explicit platform assets.
  • Tests:
    • Add tests for options parsing/serialization and matching; ensure array format preserved.

Written by Cursor Bugbot for commit d7e4801. This will update automatically on new commits. Configure here.

Copilot AI review requested due to automatic review settings November 27, 2025 19:37
Copy link
Contributor

Copilot AI left a 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 LockfileTool struct with options field and updated lockfile matching logic to require exact options match
  • Added is_current() helper method to PlatformTarget for 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.

Comment on lines +423 to +462
.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
})
Copy link

Copilot AI Nov 27, 2025

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).

Copilot uses AI. Check for mistakes.
Comment on lines +221 to +222
/// For the current platform: resolves from Settings and ToolRequest options
/// For other platforms (cross-platform mise lock): uses sensible defaults
Copy link

Copilot AI Nov 27, 2025

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.

Suggested change
/// 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.

Copilot uses AI. Check for mistakes.
@jdx jdx force-pushed the feat/lockfile-options-support branch from de66491 to 69ec1f5 Compare November 27, 2025 19:40
@jdx jdx changed the base branch from main to feat/cross-platform-lockfile November 27, 2025 19:41
Base automatically changed from feat/cross-platform-lockfile to main November 27, 2025 19:42
@jdx jdx force-pushed the feat/lockfile-options-support branch from 69ec1f5 to 3746bb2 Compare November 27, 2025 19:44
@jdx jdx force-pushed the feat/lockfile-options-support branch from 3746bb2 to 98cccee Compare November 27, 2025 19:53
@jdx jdx force-pushed the feat/lockfile-options-support branch 2 times, most recently from 8eda47e to 785824f Compare November 27, 2025 20:26
@jdx jdx changed the base branch from main to feat/lockfile-array-format November 27, 2025 20:26
@jdx jdx changed the base branch from feat/lockfile-array-format to main November 27, 2025 20:27
@jdx jdx force-pushed the feat/lockfile-options-support branch from 785824f to 6a0c56b Compare November 27, 2025 20:28
jdx and others added 2 commits November 27, 2025 12:48
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]>
@jdx jdx force-pushed the feat/lockfile-options-support branch from 93060a7 to ba2f042 Compare November 27, 2025 20:48
@jdx jdx force-pushed the feat/lockfile-options-support branch from 3b663f2 to 1f52764 Compare November 27, 2025 20:57
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]>
@jdx jdx merged commit 5f28058 into main Nov 27, 2025
16 checks passed
@jdx jdx deleted the feat/lockfile-options-support branch November 27, 2025 21:08
@github-actions
Copy link

Hyperfine Performance

mise x -- echo

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%

jdx added a commit that referenced this pull request Nov 28, 2025
## 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]>
jdx pushed a commit that referenced this pull request Nov 30, 2025
### 🚀 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)
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