Skip to content

Conversation

@jdx
Copy link
Owner

@jdx jdx commented Nov 27, 2025

Summary

Enable mise lock to generate mise.lock files with platform-specific URLs and metadata for all target platforms (linux-x64, linux-arm64, macos-x64, macos-arm64, windows-x64) even when running on a different platform.

  • Add AssetPicker::from_platform() for arbitrary target platform asset selection
  • Implement resolve_lock_info() for Aqua backend with platform-specific URL resolution
  • Add Lockfile methods: all_platform_keys(), set_platform_info(), write()
  • Rewrite CLI to process tools in parallel with configurable --jobs limit
  • Default to 5 common platforms + existing in lockfile + current platform
  • Support --platform flag for selective platform targeting
  • Graceful error handling (warn and continue)

Usage Examples

# Generate lockfile for all 5 default platforms
mise lock

# Generate for specific platforms only
mise lock --platform linux-x64,macos-arm64

# Preview what would be generated
mise lock --dry-run

# Update only specific tools
mise lock "aqua:jqlang/jq"

Generated Lockfile Format

[[tools."aqua:jqlang/jq"]]
version = "1.7.1"
backend = "aqua:jqlang/jq"

[tools."aqua:jqlang/jq".platforms.linux-x64]
name = "jq-linux-amd64"
url = "https://github.com/jqlang/jq/releases/download/jq-1.7.1/jq-linux-amd64"

[tools."aqua:jqlang/jq".platforms.windows-x64]
name = "jq-windows-amd64.exe"
url = "https://github.com/jqlang/jq/releases/download/jq-1.7.1/jq-windows-amd64.exe"

Test plan

  • Unit tests pass (mise run test:unit)
  • E2E tests updated and pass (mise run test:e2e test_lock test_lock_creation test_lock_future)
  • Clippy passes
  • Manual testing with aqua tools (jq, yq, fd)

🤖 Generated with Claude Code


Note

Enables mise lock to generate and update platform-specific URLs for multiple target platforms in parallel, using Aqua backend resolution and new lockfile APIs, with platform filtering and dry-run support.

  • CLI (src/cli/lock.rs)
    • Implement cross-platform lockfile generation with default 5 platforms (+ current/existing).
    • Add parallel processing with configurable --jobs; show progress and concise summaries.
    • Support --platform filtering and --dry-run preview; remove --force.
    • Write results to mise.lock and report updated/skimmed entries.
  • Backend (Aqua) (src/backend/aqua.rs)
    • Add resolve_lock_info(tv, target) to resolve platform-specific URLs (GitHub releases/archives/HTTP) without installation.
    • Map target OS/arch, handle version tags/prefixes, and return PlatformInfo (name/url).
  • Lockfile (src/lockfile.rs)
    • Add all_platform_keys(), set_platform_info(...), and public write().
    • Preserve/merge platform data; expose platform key discovery.
  • E2E Tests
    • Rewrite tests to validate cross-platform generation, platform filtering, tool filtering, dry-run, and help output for aqua tools (jq/yq/fd).

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

Copilot AI review requested due to automatic review settings November 27, 2025 19:01
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 implements cross-platform lockfile generation for mise lock, enabling the command to generate platform-specific URLs and metadata for all target platforms regardless of the current platform. The implementation adds parallel processing with configurable job limits and graceful error handling.

Key changes:

  • Cross-platform asset resolution via AssetPicker::from_platform() for arbitrary target platforms
  • Aqua backend support for resolve_lock_info() with platform-specific URL resolution
  • Parallel tool processing with semaphore-based concurrency control
  • Default to 5 common platforms plus any existing lockfile platforms

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/lockfile.rs Added methods for platform key extraction, platform info updates, and public write access
src/cli/lock.rs Complete rewrite to implement parallel cross-platform lockfile generation with filtering and dry-run support
src/backend/asset_detector.rs Added from_platform() constructor for cross-platform asset selection with comprehensive tests
src/backend/aqua.rs Implemented resolve_lock_info() for platform-specific URL resolution without installation
e2e/cli/test_lock_future Updated e2e tests to verify cross-platform URL generation and platform filtering
e2e/cli/test_lock_creation Updated e2e tests to verify lockfile creation and updates with aqua tools
e2e/cli/test_lock Updated e2e tests to verify basic lockfile generation, dry-run, and filtering

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

src/cli/lock.rs Outdated
platforms: &[Platform],
lockfile: &mut Lockfile,
) -> Result<Vec<(String, String, bool)>> {
let jobs = self.jobs.unwrap_or(4);
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 default value of 4 jobs doesn't match the PR description which states 'configurable --jobs limit' with a 'Default to 5 common platforms'. Consider using a consistent default value or clarifying the distinction between job concurrency and platform count.

Suggested change
let jobs = self.jobs.unwrap_or(4);
let jobs = self.jobs.unwrap_or(5);

Copilot uses AI. Check for mistakes.
Comment on lines 203 to 210
let target_libc = if let Some(qualifier) = &platform.qualifier {
qualifier.clone()
} else if platform.os == "windows" {
"msvc".to_string()
} else {
// Default to gnu for Linux/macOS when no qualifier specified
"gnu".to_string()
};
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 default libc selection logic assumes 'gnu' for all non-Windows platforms without qualifiers. This may not be accurate for all cases (e.g., Alpine Linux typically uses musl). Consider documenting this assumption or adding more specific platform detection.

Copilot uses AI. Check for mistakes.
Comment on lines +309 to +311
let myself: std::collections::HashSet<&str> =
["all", target_os, target_arch, os_arch.as_str()].into();
if !envs.is_empty() && envs.is_disjoint(&myself) {
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.

[nitpick] The variable name 'myself' is unclear in this context. Consider renaming to 'current_env_variants' or 'target_env_set' to better reflect that it represents the various environment identifiers for the target platform.

Suggested change
let myself: std::collections::HashSet<&str> =
["all", target_os, target_arch, os_arch.as_str()].into();
if !envs.is_empty() && envs.is_disjoint(&myself) {
let current_env_variants: std::collections::HashSet<&str> =
["all", target_os, target_arch, os_arch.as_str()].into();
if !envs.is_empty() && envs.is_disjoint(&current_env_variants) {

Copilot uses AI. Check for mistakes.
@jdx jdx force-pushed the feat/cross-platform-lockfile branch from 267acea to e015c77 Compare November 27, 2025 19:05
@jdx jdx force-pushed the feat/cross-platform-lockfile branch 4 times, most recently from 2b0b5ab to f5318c7 Compare November 27, 2025 19:20
Enable `mise lock` to generate platform-specific URLs and metadata for
all target platforms (linux-x64, linux-arm64, macos-x64, macos-arm64,
windows-x64) even when running on a different platform.

Key changes:
- Add AssetPicker::from_platform() for arbitrary target platforms
- Implement resolve_lock_info() for Aqua backend with platform mapping
- Add Lockfile methods: all_platform_keys(), set_platform_info(), write()
- Rewrite CLI to process tools in parallel with --jobs limit
- Default to 5 common platforms + existing in lockfile + current
- Support --platform flag for selective platform targeting
- Update E2E tests for new implementation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
@jdx jdx force-pushed the feat/cross-platform-lockfile branch from f5318c7 to e1c06ae Compare November 27, 2025 19:23
@jdx jdx enabled auto-merge (squash) November 27, 2025 19:29
@jdx jdx merged commit 30a71da into main Nov 27, 2025
27 checks passed
@jdx jdx deleted the feat/cross-platform-lockfile branch November 27, 2025 19:42
@github-actions
Copy link

Hyperfine Performance

mise x -- echo

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2025.11.10 x -- echo 19.8 ± 0.6 18.5 25.5 1.00
mise x -- echo 20.3 ± 0.8 18.8 24.1 1.03 ± 0.05

mise env

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2025.11.10 env 20.0 ± 1.3 18.0 26.8 1.02 ± 0.07
mise env 19.5 ± 0.7 18.2 22.1 1.00

mise hook-env

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2025.11.10 hook-env 19.5 ± 0.6 18.1 23.0 1.00
mise hook-env 20.0 ± 0.7 18.2 23.2 1.03 ± 0.05

mise ls

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2025.11.10 ls 16.8 ± 0.5 15.6 19.0 1.00
mise ls 17.3 ± 0.7 15.7 20.4 1.03 ± 0.05

xtasks/test/perf

Command mise-2025.11.10 mise Variance
install (cached) 115ms 110ms +4%
ls (cached) 68ms 68ms +0%
bin-paths (cached) 74ms 74ms +0%
task-ls (cached) 441ms 449ms -1%

jdx added a commit that referenced this pull request 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

```toml
[[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

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

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Adds lockfile `options` with exact-match semantics and backend/plugin
APIs to resolve artifact-affecting options, updating lock/merge logic
and implementing across major backends and core plugins.
> 
> - **Lockfile/Core**:
> - Add `options` to `LockfileTool` (parsed/serialized; only when
non-empty).
> - Match `get_locked_version` by version prefix AND exact `options`;
merge by version+`options`.
>   - Update `set_platform_info` to store per-version `options`.
> - Convert `ToolVersionList` -> lockfile including backend-resolved
`options`.
> - Add `Backend::resolve_lockfile_options()` (default empty) and
`PlatformTarget::is_current()`.
> - **Backends**:
> - `github`, `ubi`, `cargo`, `go`, `pipx`: implement
`resolve_lockfile_options()` for artifact-affecting keys (e.g.,
`asset_pattern`, `exe`, `features`, `tags`, `uvx`, etc.).
> - `aqua`: improve version detection from URLs (support package
`version_prefix`).
> - **Core Plugins**:
> - `core:python`, `core:node`, `core:erlang`, `core:ruby`: implement
`resolve_lockfile_options()` for settings-based flags (e.g., `compile`,
`flavor`, `ruby_install`, precompiled variants).
> - **CLI/Tooling**:
> - `mise lock`: generate per-platform entries using resolved `options`;
parallel task collects and writes `options`.
>   - Backend discovery uses `get_locked_backend()` from lockfile.
> - `xtasks/release-plz`: run `mise lock`; include additional files in
commit.
> - **Tests**:
> - Add tests for `options` parse/serialize and exact-match behavior;
ensure array format persists.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
1f52764. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Claude <[email protected]>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
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