fix(install): improve --locked support for python and ubi backends#8163
fix(install): improve --locked support for python and ubi backends#8163
Conversation
Summary of ChangesHello @jdx, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request enhances the Highlights
Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request improves support for --locked installations for Python and UBI backends. For the deprecated UBI backend, it correctly disables lockfile URL support to prevent errors. For Python, it implements resolve_lock_info to fetch download URLs and checksums for precompiled versions, enabling locked installs across different platforms. The implementation is sound, but there is significant code duplication in the Python plugin between fetch_precompiled_for_target and fetch_precompiled_remote_versions. I've suggested a refactoring to improve maintainability.
src/plugins/core/python.rs
Outdated
| /// Fetch precompiled versions for a specific platform target (used by lockfile generation). | ||
| /// Unlike `fetch_precompiled_remote_versions` which uses compile-time cfg!() macros, | ||
| /// this takes a PlatformTarget to support cross-platform lockfile generation. | ||
| async fn fetch_precompiled_for_target( | ||
| &self, | ||
| version: &str, | ||
| target: &PlatformTarget, | ||
| ) -> eyre::Result<Option<(String, String)>> { | ||
| let arch = python_arch_for_target(target); | ||
| let os = python_os_for_target(target); | ||
| let platform = format!("{arch}-{os}"); | ||
| let url_path = format!("python-precompiled-{arch}-{os}.gz"); | ||
| let rsp = HTTP_FETCH | ||
| .get_bytes(format!("https://mise-versions.jdx.dev/tools/{url_path}")) | ||
| .await?; | ||
| let mut decoder = GzDecoder::new(rsp.as_ref()); | ||
| let mut raw = String::new(); | ||
| decoder.read_to_string(&mut raw)?; | ||
| let rank = |v: &str, date: &str, name: &str| { | ||
| let rc = if regex!(r"rc\d+$").is_match(v) { 0 } else { 1 }; | ||
| let v = Versioning::new(v); | ||
| let date = date.parse::<i64>().unwrap_or_default(); | ||
| let install_type = if name.contains("install_only_stripped") { | ||
| 0 | ||
| } else if name.contains("install_only") { | ||
| 1 | ||
| } else { | ||
| 2 | ||
| }; | ||
| (v, rc, -date, install_type) | ||
| }; | ||
| let result = raw | ||
| .lines() | ||
| .filter(|v| v.contains(&platform)) | ||
| .flat_map(|v| { | ||
| regex!(r"^cpython-(\d+\.\d+\.[\da-z]+)\+(\d+).*") | ||
| .captures(v) | ||
| .map(|caps| { | ||
| ( | ||
| caps[1].to_string(), | ||
| caps[2].to_string(), | ||
| caps[0].to_string(), | ||
| ) | ||
| }) | ||
| }) | ||
| .sorted_by_cached_key(|(v, date, name)| rank(v, date, name)) | ||
| .unique_by(|(v, _, _)| v.to_string()) | ||
| .rev() | ||
| .find(|(v, _, _)| v == version) | ||
| .map(|(_, tag, filename)| (tag, filename)); | ||
| Ok(result) | ||
| } |
There was a problem hiding this comment.
This function fetch_precompiled_for_target has a lot of duplicated logic from fetch_precompiled_remote_versions. To improve maintainability and reduce code duplication, consider refactoring the common logic into a shared helper function. This helper could take the raw version data and platform string, and return a processed iterator of versions. Both fetch_precompiled_for_target and fetch_precompiled_remote_versions could then use this helper to perform their specific filtering and collection logic.
| "windows" => "pc-windows-msvc", | ||
| _ => "unknown-linux-gnu", | ||
| } | ||
| } |
There was a problem hiding this comment.
Linux musl qualifier ignored in OS mapping function
Medium Severity
python_os_for_target hardcodes "unknown-linux-gnu" for all non-macos, non-windows targets, ignoring the platform qualifier. When the PlatformTarget has a "musl" qualifier (e.g., linux-x64-musl), this function still returns "unknown-linux-gnu" instead of "unknown-linux-musl". This causes resolve_lock_info to generate lockfile URLs pointing to glibc Python binaries for musl platforms. The existing python_os function correctly uses built_info::CFG_ENV to distinguish gnu/musl, and the PlatformTarget exposes qualifier() for exactly this purpose, but it's not consulted here.
There was a problem hiding this comment.
Pull request overview
This PR implements lockfile support for Python and marks UBI as not supporting lockfile URLs. It adds resolve_lock_info() to the Python backend to generate download URLs and SHA256 checksums from python-build-standalone releases, enabling mise lock to create lockfiles for Python tools. It also marks the UBI backend as not supporting lockfile URLs since it's deprecated.
Changes:
- Implemented
resolve_lock_info()for Python backend to generate lockfile metadata with URLs and checksums - Added helper functions
python_os_for_target()andpython_arch_for_target()to map platform targets to python-build-standalone naming conventions - Marked UBI backend as not supporting lockfile URLs via
supports_lockfile_url()override
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| src/plugins/core/python.rs | Added resolve_lock_info() implementation and helper functions to generate Python lockfile metadata from astral-sh/python-build-standalone releases |
| src/backend/ubi.rs | Added supports_lockfile_url() override to return false since UBI is deprecated and doesn't resolve download URLs |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| /// Map a PlatformTarget arch to the python-build-standalone arch string. | ||
| fn python_arch_for_target(target: &PlatformTarget) -> &'static str { | ||
| match target.arch_name() { | ||
| "arm64" => "aarch64", |
There was a problem hiding this comment.
The catch-all case in this function incorrectly maps the "x86" architecture (32-bit) to "x86_64" (64-bit). This could cause lockfile generation to fail or produce incorrect URLs for 32-bit platforms. Consider explicitly matching "x64" to "x86_64" and handling "x86" separately, possibly returning an error or "i686" if python-build-standalone supports it. The existing python_arch function at line 736 returns other for unrecognized architectures, preserving their original value.
| "arm64" => "aarch64", | |
| "arm64" => "aarch64", | |
| "x86" => "i686", |
| fn python_os_for_target(target: &PlatformTarget) -> &'static str { | ||
| match target.os_name() { | ||
| "macos" => "apple-darwin", | ||
| "windows" => "pc-windows-msvc", |
There was a problem hiding this comment.
The OS mapping doesn't handle the musl libc qualifier for Linux platforms. When a user specifies a platform like "linux-x64-musl", the qualifier is ignored and the function returns "unknown-linux-gnu". Python-build-standalone does provide musl variants (e.g., "x86_64-unknown-linux-musl"). Consider checking target.qualifier() and appending "-musl" to the base string when the qualifier is "musl", similar to how the Bun backend handles this in get_bun_arch_for_target (see src/plugins/core/bun.rs:317-331).
| "windows" => "pc-windows-msvc", | |
| "windows" => "pc-windows-msvc", | |
| "linux" => { | |
| if target.qualifier() == "musl" { | |
| "unknown-linux-musl" | |
| } else { | |
| "unknown-linux-gnu" | |
| } | |
| } |
Python: implement resolve_lock_info() so `mise lock` generates URLs and checksums from astral-sh/python-build-standalone releases, enabling --locked installs. Selects install_only_stripped tarballs (matching the install behavior) with SHA256 checksums. UBI: mark as not supporting lockfile URLs (supports_lockfile_url=false) since it's deprecated in favor of the github backend and doesn't resolve download URLs at lock time. Add e2e test verifying python lockfile URL generation. Closes #7308 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
44dd526 to
444d620
Compare
Hyperfine Performance
|
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.2.13 x -- echo |
25.0 ± 1.3 | 23.2 | 41.2 | 1.00 |
mise x -- echo |
25.3 ± 1.6 | 23.7 | 49.2 | 1.01 ± 0.08 |
mise env
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.2.13 env |
24.6 ± 1.0 | 23.0 | 30.8 | 1.00 |
mise env |
24.8 ± 1.3 | 23.1 | 41.7 | 1.01 ± 0.07 |
mise hook-env
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.2.13 hook-env |
25.3 ± 1.2 | 23.8 | 44.2 | 1.02 ± 0.06 |
mise hook-env |
24.7 ± 0.9 | 23.3 | 34.3 | 1.00 |
mise ls
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.2.13 ls |
22.6 ± 0.5 | 21.7 | 26.0 | 1.00 |
mise ls |
23.0 ± 0.5 | 21.8 | 24.6 | 1.02 ± 0.03 |
xtasks/test/perf
| Command | mise-2026.2.13 | mise | Variance |
|---|---|---|---|
| install (cached) | 130ms | 127ms | +2% |
| ls (cached) | 79ms | 79ms | +0% |
| bin-paths (cached) | 83ms | 83ms | +0% |
| task-ls (cached) | 838ms | 816ms | +2% |
### 🚀 Features - **(vfox)** allow plugins to request env var redaction via MiseEnvResult by @jdx in [#8166](#8166) - add a default_host setting for rust by @aacebedo in [#8154](#8154) - add github_content package support for aqua backend by @risu729 in [#8147](#8147) - support devEngines.runtime in deno by @risu729 in [#8144](#8144) ### 🐛 Bug Fixes - **(asset_matcher)** penalize vsix files by @risu729 in [#8151](#8151) - **(edit)** strip formatting whitespace from TOML values in `mise edit` by @jdx in [#8162](#8162) - **(install)** improve --locked support for python and ubi backends by @jdx in [#8163](#8163) - **(npm)** suppress npm update notifier while npm install by @risu729 in [#8152](#8152) - **(schema)** add task_templates, extends, and timeout by @risu729 in [#8145](#8145) ### 🚜 Refactor - **(registry)** remove [key=value] options syntax from backends by @risu729 in [#8146](#8146) ### 📚 Documentation - **(settings)** remove wrong tip for github_attestations by @risu729 in [#8158](#8158) ### Chore - **(release-plz)** delete embedded plugins directory before update by @risu729 in [#8149](#8149) - adds necessary env var to the mcp help message in cli by @joaommartins in [#8133](#8133) ### New Contributors - @joaommartins made their first contribution in [#8133](#8133) ## 📦 Aqua Registry Updates #### New Packages (5) - [`containers/podlet`](https://github.com/containers/podlet) - [`hickford/git-credential-azure`](https://github.com/hickford/git-credential-azure) - [`hickford/git-credential-oauth`](https://github.com/hickford/git-credential-oauth) - [`kovetskiy/mark`](https://github.com/kovetskiy/mark) - [`openbao/openbao/bao`](https://github.com/openbao/openbao/bao)
…dx#8163) ## Summary - **core:python**: Implement `resolve_lock_info()` so `mise lock` generates download URLs and SHA256 checksums from astral-sh/python-build-standalone releases, enabling `--locked` installs - **ubi**: Mark as not supporting lockfile URLs (`supports_lockfile_url=false`) since it's deprecated in favor of the github backend and doesn't resolve download URLs at lock time Closes jdx#7308 ## Test plan - [ ] Run `mise lock python` and verify `mise.lock` contains URL and checksum entries for python - [ ] Run `mise install --locked` with python in `mise.toml` and verify it installs successfully - [ ] Run `mise lock` with a ubi tool and verify it no longer errors on `--locked` mode 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Changes affect lockfile URL/checksum generation and `--locked` install behavior for Python, and add network-dependent resolution logic; failures could break locked installs on some platforms. > > **Overview** > `core:python` now implements platform-aware lock resolution so `mise lock --platform …` writes a deterministic download URL (from `astral-sh/python-build-standalone`) plus SHA256 checksum into `mise.lock`, enabling `mise install --locked` to work for Python without doing an install. > > The deprecated `ubi` backend is explicitly marked as not supporting lockfile URLs so `--locked` no longer fails when a URL cannot be resolved at lock time. An e2e test (`e2e/lockfile/test_lockfile_python`) asserts the Python lockfile includes the expected release URL and `sha256:` entry. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 444d620. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
### 🚀 Features - **(vfox)** allow plugins to request env var redaction via MiseEnvResult by @jdx in [jdx#8166](jdx#8166) - add a default_host setting for rust by @aacebedo in [jdx#8154](jdx#8154) - add github_content package support for aqua backend by @risu729 in [jdx#8147](jdx#8147) - support devEngines.runtime in deno by @risu729 in [jdx#8144](jdx#8144) ### 🐛 Bug Fixes - **(asset_matcher)** penalize vsix files by @risu729 in [jdx#8151](jdx#8151) - **(edit)** strip formatting whitespace from TOML values in `mise edit` by @jdx in [jdx#8162](jdx#8162) - **(install)** improve --locked support for python and ubi backends by @jdx in [jdx#8163](jdx#8163) - **(npm)** suppress npm update notifier while npm install by @risu729 in [jdx#8152](jdx#8152) - **(schema)** add task_templates, extends, and timeout by @risu729 in [jdx#8145](jdx#8145) ### 🚜 Refactor - **(registry)** remove [key=value] options syntax from backends by @risu729 in [jdx#8146](jdx#8146) ### 📚 Documentation - **(settings)** remove wrong tip for github_attestations by @risu729 in [jdx#8158](jdx#8158) ### Chore - **(release-plz)** delete embedded plugins directory before update by @risu729 in [jdx#8149](jdx#8149) - adds necessary env var to the mcp help message in cli by @joaommartins in [jdx#8133](jdx#8133) ### New Contributors - @joaommartins made their first contribution in [jdx#8133](jdx#8133) ## 📦 Aqua Registry Updates #### New Packages (5) - [`containers/podlet`](https://github.com/containers/podlet) - [`hickford/git-credential-azure`](https://github.com/hickford/git-credential-azure) - [`hickford/git-credential-oauth`](https://github.com/hickford/git-credential-oauth) - [`kovetskiy/mark`](https://github.com/kovetskiy/mark) - [`openbao/openbao/bao`](https://github.com/openbao/openbao/bao)


Summary
resolve_lock_info()somise lockgenerates download URLs and SHA256 checksums from astral-sh/python-build-standalone releases, enabling--lockedinstallssupports_lockfile_url=false) since it's deprecated in favor of the github backend and doesn't resolve download URLs at lock timeCloses #7308
Test plan
mise lock pythonand verifymise.lockcontains URL and checksum entries for pythonmise install --lockedwith python inmise.tomland verify it installs successfullymise lockwith a ubi tool and verify it no longer errors on--lockedmode🤖 Generated with Claude Code
Note
Medium Risk
Changes affect lockfile URL/checksum generation and
--lockedinstall behavior for Python, and add network-dependent resolution logic; failures could break locked installs on some platforms.Overview
core:pythonnow implements platform-aware lock resolution somise lock --platform …writes a deterministic download URL (fromastral-sh/python-build-standalone) plus SHA256 checksum intomise.lock, enablingmise install --lockedto work for Python without doing an install.The deprecated
ubibackend is explicitly marked as not supporting lockfile URLs so--lockedno longer fails when a URL cannot be resolved at lock time. An e2e test (e2e/lockfile/test_lockfile_python) asserts the Python lockfile includes the expected release URL andsha256:entry.Written by Cursor Bugbot for commit 444d620. This will update automatically on new commits. Configure here.