Skip to content

feat(backend): add version timestamps for spm, conda, and gem backends#7383

Merged
jdx merged 6 commits intomainfrom
feat/version-info-backends
Dec 18, 2025
Merged

feat(backend): add version timestamps for spm, conda, and gem backends#7383
jdx merged 6 commits intomainfrom
feat/version-info-backends

Conversation

@jdx
Copy link
Copy Markdown
Owner

@jdx jdx commented Dec 18, 2025

Summary

  • spm: Use existing created_at from GitHub releases and released_at from GitLab releases
  • conda: Parse upload_time field from anaconda.org API response
  • gem: Use RubyGems API (/api/v1/versions/{gem}.json) with created_at, respecting custom gem sources from gem sources

This enables time-based version filtering (e.g., mise use tool@latest --before 2024-01-01) for these backends.

Test plan

  • Verify mise ls-remote returns versions for spm, conda, and gem tools
  • Verify version timestamps are populated in version info responses

🤖 Generated with Claude Code


Note

Refactors backends to return VersionInfo (with optional timestamps) and populates created_at for many providers (conda, gem, spm, github/gitlab, npm, etc.), updates caching, and passes proxy envs in e2e.

  • Backend API:
    • Replace _list_remote_versions_with_info with unified _list_remote_versions returning Vec<VersionInfo>; list_remote_versions_with_info now caches and calls unified method.
    • Update all backends to new signature (e.g., aqua, asdf, cargo, conda, dotnet, github, go, http, npm, pipx, spm, ubi, vfox).
  • Timestamps/metadata:
    • conda: group by version and use upload_time for created_at; bypass shared cache due to channel.
    • gem: switch to RubyGems API (/api/v1/versions/*.json) with created_at; detect custom source via gem sources.
    • spm: use GitHub/GitLab releases with created_at.
    • github/gitlab, npm, pipx, cargo, bun, deno, elixir, erlang, go (core), java (with GA/EA cache bypass), node, python, ruby (incl. Windows), rust, swift, zig: return VersionInfo and attach release dates where available.
  • Misc:
    • e2e/run_test: pass through proxy env vars inside isolated env (http_proxy, https_proxy, etc.).

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

Copilot AI review requested due to automatic review settings December 18, 2025 14:15
Copy link
Copy Markdown
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 version timestamp support for three backends (spm, conda, and gem) to enable time-based version filtering. Each backend is updated to implement _list_remote_versions_with_info instead of _list_remote_versions, returning VersionInfo objects that include version strings and their creation timestamps.

  • Leverages existing timestamp fields from GitHub/GitLab release APIs for spm
  • Parses upload_time from anaconda.org API for conda packages
  • Switches from gem info CLI to RubyGems HTTP API for gem versions
  • Removes obsolete gem version parsing logic and associated tests

Reviewed changes

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

File Description
src/backend/spm.rs Updates to map GitHub created_at and GitLab released_at fields into VersionInfo objects
src/backend/gem.rs Replaces CLI-based version fetching with RubyGems API calls, adds gem source detection, removes parsing helper and tests
src/backend/conda.rs Extracts upload_time from package files and tracks latest timestamp per version

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

Comment thread src/backend/gem.rs Outdated

/// Cached gem source URL (global, fetched once)
static GEM_SOURCE: LazyLock<String> = LazyLock::new(|| {
let output = cmd!("gem", "sources").read().unwrap_or_default();
Copy link

Copilot AI Dec 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The unwrap_or_default() silently swallows errors from gem sources. If the gem command fails or is not available, this will fall through to the default rubygems.org without informing the user. Consider logging a warning when the command fails so users know their custom gem source configuration wasn't respected.

Suggested change
let output = cmd!("gem", "sources").read().unwrap_or_default();
let output = match cmd!("gem", "sources").read() {
Ok(output) => output,
Err(err) => {
eprintln!(
"warning: failed to run `gem sources` ({}). Falling back to default gem source https://rubygems.org/.",
err
);
String::new()
}
};

Copilot uses AI. Check for mistakes.
Comment thread src/backend/conda.rs Outdated
.and_modify(|existing| {
// Keep the latest upload time for each version
if let Some(new_time) = &f.upload_time {
if existing.is_none() || existing.as_ref().is_some_and(|e| new_time > e) {
Copy link

Copilot AI Dec 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic for determining the latest upload time can be simplified. The condition existing.as_ref().is_some_and(|e| new_time > e) will never be true when existing.is_none() is true, making the first check redundant. Consider simplifying to: if existing.as_ref().map_or(true, |e| new_time > e).

Suggested change
if existing.is_none() || existing.as_ref().is_some_and(|e| new_time > e) {
if existing.as_ref().map_or(true, |e| new_time > e) {

Copilot uses AI. Check for mistakes.
@jdx jdx force-pushed the feat/version-info-backends branch from 74c271a to 4256650 Compare December 18, 2025 14:24
Comment thread src/backend/gem.rs Outdated
Implement `_list_remote_versions_with_info` for three backends to provide
version release dates, enabling time-based version filtering:

- **spm**: Use existing `created_at` from GitHub releases and `released_at`
  from GitLab releases
- **conda**: Parse `upload_time` field from anaconda.org API response
- **gem**: Use RubyGems API (`/api/v1/versions/{gem}.json`) with `created_at`,
  respecting custom gem sources from `gem sources`

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

Co-Authored-By: Claude Opus 4.5 <[email protected]>
@jdx jdx force-pushed the feat/version-info-backends branch 3 times, most recently from 9396b50 to b5bcda2 Compare December 18, 2025 14:37
Cache the gem source URL after first successful detection using
OnceCell. The first call to get_gem_source() uses the mise-managed
Ruby environment to run `gem sources`, then caches the result
globally so subsequent calls return instantly.

Uses get_or_try_init to only memoize on success - if `gem sources`
fails, a warning is shown and rubygems.org is used as fallback
without caching (allowing retry on next call).

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

Co-Authored-By: Claude Opus 4.5 <[email protected]>
@jdx jdx force-pushed the feat/version-info-backends branch from b5bcda2 to 0798572 Compare December 18, 2025 14:41
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Dec 18, 2025

Hyperfine Performance

mise x -- echo

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2025.12.11 x -- echo 19.8 ± 0.4 19.1 23.6 1.00
mise x -- echo 20.2 ± 0.5 19.2 21.5 1.02 ± 0.03

mise env

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2025.12.11 env 19.6 ± 0.9 18.9 33.8 1.00
mise env 20.2 ± 0.5 18.9 24.1 1.03 ± 0.05

mise hook-env

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2025.12.11 hook-env 19.4 ± 0.4 18.5 21.6 1.00 ± 0.04
mise hook-env 19.4 ± 0.7 18.6 29.2 1.00

mise ls

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2025.12.11 ls 17.0 ± 0.7 16.3 27.6 1.00
mise ls 17.4 ± 0.4 16.6 19.6 1.02 ± 0.05

xtasks/test/perf

Command mise-2025.12.11 mise Variance
install (cached) 108ms 109ms +0%
ls (cached) 65ms 65ms +0%
bin-paths (cached) 71ms 71ms +0%
task-ls (cached) 278ms 278ms +0%

The Java backend has separate caches for GA and EA release types via
fetch_java_metadata, but the Backend trait's list_remote_versions_with_info
used a shared cache that didn't account for release_type. This caused
fuzzy version matching to fail when installing EA versions after GA
versions were cached.

Override list_remote_versions_with_info in the Java backend to bypass
the shared cache and use the release-type-aware caching directly.

Also adds proxy environment variable passthrough in e2e test runner
for environments that require proxy access.

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

Co-Authored-By: Claude Opus 4.5 <[email protected]>
The conda backend has a 'channel' option that affects which versions
are available. Override list_remote_versions_with_info to bypass the
shared remote_versions cache, similar to the fix for Java's release_type
option.

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

Co-Authored-By: Claude Opus 4.5 <[email protected]>
@jdx jdx enabled auto-merge (squash) December 18, 2025 15:38
@jdx jdx merged commit e0f3fff into main Dec 18, 2025
28 checks passed
@jdx jdx deleted the feat/version-info-backends branch December 18, 2025 15:39
jekis913 added a commit to jekis913/mise that referenced this pull request Dec 19, 2025
* upstream/main:
  feat(backend): add version timestamps for spm, conda, and gem backends (jdx#7383)
  fix(aqua): improve security feature detection (jdx#7385)
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.

3 participants