Skip to content

feat(spm): add artifact bundle support#9825

Merged
jdx merged 4 commits into
jdx:mainfrom
ikesyo:feat-spm-artifactbundle
May 15, 2026
Merged

feat(spm): add artifact bundle support#9825
jdx merged 4 commits into
jdx:mainfrom
ikesyo:feat-spm-artifactbundle

Conversation

@ikesyo

@ikesyo ikesyo commented May 13, 2026

Copy link
Copy Markdown
Contributor

Summary

  • add default-on SwiftPM artifact bundle installation with source-build fallback
  • add artifactbundle, artifactbundle_asset, and spm.artifactbundle_only controls
  • cover asset selection, target triple matching, artifact bundle executable filtering, and a SwiftFormat e2e install

Tests

  • cargo fmt --check
  • cargo test backend::spm
  • mise run test:e2e e2e/core/test_swift_slow
  • mise run lint

Discussion: #9691

This PR description was generated by an AI coding assistant.

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request introduces support for SwiftPM artifact bundles in the SPM backend, allowing mise to install prebuilt binaries from *.artifactbundle.zip assets instead of building from source. It includes new configuration options like artifactbundle and artifactbundle_asset, along with a global spm.artifactbundle_only setting. Review feedback highlighted the need for proper checksum verification using verify_checksum to ensure integrity and lockfile compatibility. Additionally, improvements were suggested regarding the efficiency of bundle scanning and the ordering of platform metadata updates.

Comment thread src/backend/spm.rs Outdated
Comment on lines +342 to +347
let checksum = if let Some(digest) = &asset.digest {
digest.clone()
} else {
let h = hash::file_hash_blake3(&download_path, Some(ctx.pr.as_ref()))?;
format!("blake3:{h}")
};

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.

security-high high

The current implementation does not verify the integrity of the downloaded artifact bundle. If asset.digest is provided by the API, it is used as the checksum without hashing the file to verify it matches. Additionally, this logic bypasses the lockfile's checksum verification in --locked mode because it doesn't check if a checksum already exists for the platform.

You should use self.verify_checksum which correctly handles verification against existing lockfile entries, generates new checksums when needed, and enforces integrity checks.

Comment thread src/backend/spm.rs Outdated
Comment on lines +378 to +382
let platform_key = self.get_platform_key();
let platform_info = tv.lock_platforms.entry(platform_key).or_default();
platform_info.url = Some(asset.url.clone());
platform_info.url_api = asset.url_api.clone();
platform_info.checksum = Some(checksum);

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.

medium

This block is redundant if the platform information is updated and verified earlier in the function. Moving the update earlier ensures that the ToolVersion object is correctly populated before verification and extraction, and avoids using the unverified checksum variable.

Comment thread src/backend/spm.rs Outdated
extract_dir: &Path,
target_triples: &[String],
) -> eyre::Result<Vec<ArtifactBundleBinary>> {
let mut bundles = file::recursive_ls(extract_dir)?

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.

medium

Using file::recursive_ls on the entire extraction directory can be inefficient if the archive contains a large number of files. Since Swift artifact bundles have a specific structure (a .artifactbundle directory containing an info.json), a more targeted search or a depth-limited walk would be more efficient.

References
  1. When adding support for a new archive format (e.g., by extending TarFormat::from_ext), ensure all relevant parts of the codebase that handle archive detection, asset scoring, and opening/extraction are updated to recognize and process the new format.

@greptile-apps

greptile-apps Bot commented May 13, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds SwiftPM artifact bundle installation support to the spm backend, enabling mise to download and install prebuilt executables from *.artifactbundle.zip release assets before falling back to a source build.

  • Introduces try_install_artifactbundle with full asset resolution, download, extraction, target-triple matching, and binary filtering. Three new per-tool options (artifactbundle, artifactbundle_asset, filter_bins) and a global setting spm.artifactbundle_only control the behavior.
  • Adds parse_swift_target_triples with HashSet-based deduplication, a break after the first matching variant per artifact, and an .artifactbundle.zip extension guard.
  • Includes comprehensive unit tests for every new function and an e2e test that installs SwiftFormat 0.61.1 via its artifact bundle.

Confidence Score: 5/5

The artifact bundle install path is well-guarded with fallback logic and all three previously flagged correctness issues are resolved.

All three issues from prior review threads are fixed. The two remaining observations are minor disk and cache inefficiencies with no functional impact on installation correctness or user data.

src/backend/spm.rs — the remote_version_listing_tool_option_keys array and the fallback cleanup path in try_install_artifactbundle are worth a second look.

Important Files Changed

Filename Overview
src/backend/spm.rs Adds full artifact bundle install path: asset resolution, download, extraction, triple matching, binary filtering, and source-build fallback. Previously flagged issues (Vec::dedup, first-variant break, extension validation) are all addressed.
docs/dev-tools/backends/spm.md Adds clear documentation for artifactbundle, artifactbundle_asset, and spm.artifactbundle_only with accurate TOML examples.
e2e/core/test_swift_slow Adds an e2e assertion that installs SwiftFormat 0.61.1 via artifact bundle and verifies the version output.
schema/mise.json Adds spm.artifactbundle_only boolean setting to the JSON schema with correct type, description, and default.
settings.toml Registers spm.artifactbundle_only with correct env var, default, and description, consistent with the cargo.binstall_only pattern.

Reviews (4): Last reviewed commit: "fix(spm): remove needless borrows" | Re-trigger Greptile

Comment thread src/backend/spm.rs
Comment thread src/backend/spm.rs
Comment thread src/backend/spm.rs Outdated
@ikesyo ikesyo force-pushed the feat-spm-artifactbundle branch from fd2a703 to 25c451f Compare May 13, 2026 05:21
ikesyo and others added 3 commits May 13, 2026 14:32
Co-authored-by: Codex <noreply@openai.com>
Co-authored-by: Codex <noreply@openai.com>
Co-authored-by: Codex <noreply@openai.com>
@ikesyo ikesyo force-pushed the feat-spm-artifactbundle branch from 86cfbe0 to dfa0166 Compare May 13, 2026 05:33
Co-authored-by: Codex <noreply@openai.com>
@jdx jdx merged commit 74cc066 into jdx:main May 15, 2026
33 checks passed
mise-en-dev added a commit that referenced this pull request May 15, 2026
### 🚀 Features

- **(config)** add shell to watch_files run by @risu729 in
[#9810](#9810)
- **(spm)** add artifact bundle support by @ikesyo in
[#9825](#9825)

### 🐛 Bug Fixes

- **(aqua)** reject registry-invalid latest tags by @risu729 in
[#9834](#9834)
- **(patrons)** point sponsor link to https://en.dev by @jdx in
[#9868](#9868)
- **(vfox)** respect default inline shell in cmd.exec by @risu729 in
[#9837](#9837)
- github oauth device flow paths by @jasisk in
[#9791](#9791)

### 📚 Documentation

- Update Walkthrough guide by @thernstig in
[#9853](#9853)

### ⚡ Performance

- **(config)** skip tera render for plain strings by @risu729 in
[#9833](#9833)

### 📦️ Dependency Updates

- update ghcr.io/jdx/mise:rpm docker digest to d2471f2 by @renovate[bot]
in [#9879](#9879)
- update rust docker digest to 5b1e348 by @renovate[bot] in
[#9880](#9880)
- update ghcr.io/jdx/mise:deb docker digest to 0cde829 by @renovate[bot]
in [#9878](#9878)
- update ubuntu docker tag to resolute-20260421 by @renovate[bot] in
[#9881](#9881)
- update ghcr.io/jdx/mise:alpine docker digest to 2d0ea74 by
@renovate[bot] in [#9877](#9877)
- update rust crate phf to 0.13 by @renovate[bot] in
[#9884](#9884)
- update rust crate phf_codegen to 0.13 by @renovate[bot] in
[#9883](#9883)

### 📦 Registry

- use aqua backend for npm by @risu729 in
[#9762](#9762)
- add aqua for buck2 prereleases by @risu729 in
[#9805](#9805)
- add SonarQube CLI
([aqua:SonarSource/sonarqube-cli](https://github.com/SonarSource/sonarqube-cli))
by @3PeatVR in [#9824](#9824)

### New Contributors

- @3PeatVR made their first contribution in
[#9824](#9824)
- @ikesyo made their first contribution in
[#9825](#9825)
- @thernstig made their first contribution in
[#9853](#9853)

## 📦 Aqua Registry Updates

### New Packages (4)

- [`SurgeDM/Surge`](https://github.com/SurgeDM/Surge)
- [`roie/ovw`](https://github.com/roie/ovw)
- [`so-dang-cool/sigi`](https://github.com/so-dang-cool/sigi)
- [`vjeantet/alerter`](https://github.com/vjeantet/alerter)

### Updated Packages (2)

-
[`alltuner/mise-completions-sync`](https://github.com/alltuner/mise-completions-sync)
-
[`str4d/age-plugin-yubikey`](https://github.com/str4d/age-plugin-yubikey)
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