Skip to content

fix(backend): respect permissive minimum release age#10310

Merged
jdx merged 2 commits into
mainfrom
codex/fix-minimum-release-age-latest
Jun 11, 2026
Merged

fix(backend): respect permissive minimum release age#10310
jdx merged 2 commits into
mainfrom
codex/fix-minimum-release-age-latest

Conversation

@jdx

@jdx jdx commented Jun 11, 2026

Copy link
Copy Markdown
Owner

Summary

Fixes minimum_release_age handling when resolving latest through backend fast paths.

  • Treat minimum_release_age = "0s" as disabling the cutoff, matching the documented behavior.
  • Let backends expose fast-path latest release metadata so release-age filtering can validate the canonical latest release even when cached remote-version metadata is stale.
  • Populate GitHub/Forgejo latest fast-path results with created_at metadata from the release endpoint.
  • Add regression coverage for stale metadata, permissive future cutoffs, and 0s cutoff disabling.

Root Cause

latest_stable_version() returned only a version string. When minimum_release_age was active, mise checked that version against the cached full version metadata. If the canonical latest release had not yet appeared in the cached metadata list, mise treated it like an unverified/too-new release and fell back to an older cached version, producing warnings such as ignored by minimum_release_age even for permissive cutoffs.

Separately, "0s" was parsed as a timestamp at process start instead of None, so it still enabled the metadata filtering path despite the docs saying it disables the delay.

Validation

  • cargo test latest_version_tests
  • cargo test install_before::tests::test_zero_minimum_release_age_disables_cutoff
  • cargo fmt --all -- --check

Refs #10303 (comment)


Note

Medium Risk
Changes core latest-version resolution and release-age filtering used across installs; behavior is narrowed with tests but affects many backends' latest queries.

Overview
Fixes minimum_release_age so latest resolution through backend fast paths behaves as documented.

0s disables the cutoff: install_before now treats zero-duration minimum_release_age (e.g. "0s") as no release-age filter instead of a timestamp at process start.

Rich fast-path metadata: A new latest_stable_version_info hook returns VersionInfo (including created_at) from canonical upstream “latest” endpoints. GitHub/Forgejo populate it from /releases/latest. latest_version / latest_version_unfiltered prefer this hook, then fall back to the string-only fast path.

Stale cache + age filtering: When a cutoff is active, release-age checks use fast-path metadata when present, so the canonical latest can pass even if it is missing from a stale cached version list. latest_stable_candidate_allowed_by_before_date accepts fast-path candidates when the cutoff is in the future and metadata is missing or lacks a date (permissive case).

Regression tests cover stale metadata, unfiltered latest, permissive future cutoffs, and 0s disabling.

Reviewed by Cursor Bugbot for commit 39f9e63. Bugbot is set up for automated code reviews on this repo. Configure here.

Summary by CodeRabbit

  • New Features

    • Stable release resolution now returns release date and prerelease metadata.
    • Option to disable the minimum-release-age cutoff by setting duration to zero.
  • Improvements

    • Version resolution uses stable-release metadata to improve cutoff and freshness decisions.
    • Backends can provide richer stable-version information to improve accuracy.
  • Tests

    • Added and updated tests covering stable-metadata use and zero-duration cutoff behavior.

@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Adds a Backend hook returning rich VersionInfo for the absolute latest stable release (created_at and prerelease), implements it for GitHub/Forgejo, updates latest resolution to prefer that metadata for cutoff validation, and treats a zero-duration minimum_release_age as disabling the cutoff.

Changes

Latest Stable Version Metadata and Cutoff Resolution

Layer / File(s) Summary
Backend trait contract for stable version metadata
src/backend/mod.rs
Backend trait gains latest_stable_version_info, a new optional async hook returning Option<VersionInfo> for absolute latest stable releases, defaulting to Ok(None).
GitHub and Forgejo backend implementation
src/backend/github.rs
GitHub and Forgejo implement the new trait method by fetching from latest release endpoints, capturing created_at and prerelease metadata, filtering by version_prefix, and constructing VersionInfo objects with version, created_at, and prerelease fields.
Version resolution with stable metadata fast path
src/backend/mod.rs
latest_version_with_refresh is updated to use latest_stable_version_info when querying for latest. When a before_date cutoff exists, the metadata validates the candidate; without a cutoff, the candidate returns immediately if metadata is available.
Cutoff validation improvements for metadata-rich candidates
src/backend/mod.rs
latest_stable_candidate_allowed_by_before_date now returns allowed when stable candidate lacks metadata but the before cutoff is in the future; otherwise it denies, with added debug logging.
Test backend and new test coverage
src/backend/mod.rs
Test backend LatestBackend is extended with stable_info and stable_info_calls fields, a with_stable_info builder, and latest_stable_version_info implementation. New async tests validate stable metadata usage when remote cache is stale and permissive behavior when cutoff is far in the future. Fixture initialization updated.
Zero-duration cutoff disable feature
src/install_before.rs
resolve_before_date_with_excludes treats minimum_release_age of zero duration as disabling the cutoff (returns Ok(None)) for both direct and global Settings::minimum_release_age paths. New unit test verifies both behaviors.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • jdx/mise#10277: Adds minimum_release_age_excludes handling to the same release-age resolution path in src/install_before.rs.
  • jdx/mise#10279: Modifies src/install_before.rs cutoff logic with overlapping changes to minimum_release_age handling.
  • jdx/mise#10255: Also changes GitHub “latest” release fetching logic in src/backend/github.rs, related to latest/tag resolution.

Poem

🐰 I hopped through tags and timestamps bright,

Carried created_at and prerelease light,
When zero means "off", the cutoff's set free,
The latest path returns metadata for me,
A rabbit cheers the resolver's new spree.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'fix(backend): respect permissive minimum release age' accurately reflects the main change: fixing handling of minimum_release_age when resolving 'latest' through backend fast paths.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

@jdx jdx marked this pull request as ready for review June 11, 2026 18:45

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 29bfe3f. Configure here.

Comment thread src/backend/mod.rs

@coderabbitai coderabbitai 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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/backend/mod.rs`:
- Around line 1284-1296: latest_version_unfiltered currently only calls
latest_stable_version, but the new metadata hook latest_stable_version_info must
be consulted first so backends like github.rs that implement only the metadata
variant return the true canonical "absolute latest"; update
latest_version_unfiltered to call self.latest_stable_version_info(config).await,
use the returned Option<VersionInfo> (when Some) as the fast-path latest result,
and only fall back to calling self.latest_stable_version(config).await or the
cached-list resolution if the metadata hook returns None or an error, preserving
existing error handling and return types.
- Around line 1583-1610: The code unconditionally calls
list_remote_versions_with_info_with_refresh(...) even when latest.created_at is
present; change the logic in the branch handling Some(latest) so you first check
latest.created_at (and compute info = latest.created_at.as_ref().map(|_|
&latest)) and only call list_remote_versions_with_info_with_refresh and set
fallback_refresh = false if info is None (i.e., created_at missing) or the
created_at case doesn't satisfy
latest_stable_candidate_allowed_by_before_date(&version, info, before); keep
using latest_stable_candidate_allowed_by_before_date(&version, info, before) for
the final decision and ensure fallback_refresh is adjusted only when the remote
list is actually fetched.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 210da34d-f397-4807-9ff6-be94f0b17d1a

📥 Commits

Reviewing files that changed from the base of the PR and between fa0ec9d and 29bfe3f.

📒 Files selected for processing (3)
  • src/backend/github.rs
  • src/backend/mod.rs
  • src/install_before.rs

Comment thread src/backend/mod.rs
Comment thread src/backend/mod.rs
@greptile-apps

greptile-apps Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes two independent minimum_release_age bugs: "0s" is now treated as disabling the cutoff rather than anchoring it at process start, and the GitHub/Forgejo fast-path now surfaces created_at metadata so a freshly-published canonical latest release is correctly accepted (or rejected) even when the cached remote-version list is stale.

  • Adds latest_stable_version_info as a new optional trait method returning VersionInfo with created_at; existing backends that only override latest_stable_version are unaffected by the fallback chain.
  • Threads fast-path metadata into latest_version_with_refresh so date-filtering can validate the latest release without relying on the cached version list; adds a before > process_now() guard to accept candidates when the cutoff is set to a permissive future date and metadata is missing.
  • New regression tests cover the stale-metadata path, the permissive future-cutoff path, and the zero-duration short-circuit.

Confidence Score: 5/5

Safe to merge — both bug fixes are narrow and well-tested, backward compatibility is maintained for all existing backends, and the new trait method defaults to a no-op.

Both changes (zero-duration short-circuit and fast-path metadata injection) are isolated to their respective code paths, covered by dedicated regression tests, and do not alter behavior for the common minimum_release_age = "24h" case. Backends that only override latest_stable_version continue to work through the unchanged fallback chain.

No files require special attention.

Important Files Changed

Filename Overview
src/backend/mod.rs Adds latest_stable_version_info trait method with VersionInfo return, threads fast-path metadata into date-filtering logic, and adds before > process_now() guards for permissive future cutoffs; logic is sound and all branching is covered by tests.
src/backend/github.rs Replaces latest_stable_version override with latest_stable_version_info, populating created_at and prerelease from /releases/latest; field types match the struct definitions and the prerelease short-circuit is preserved.
src/install_before.rs Zero-duration guard added before parse_into_timestamp in both the inline minimum_release_age and global-settings paths; correctly short-circuits to Ok(None) and is covered by new test.

Reviews (1): Last reviewed commit: "fix(backend): use metadata fast path for..." | Re-trigger Greptile

@github-actions

Copy link
Copy Markdown

Hyperfine Performance

mise x -- echo

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.6.2 x -- echo 21.0 ± 2.8 17.6 34.3 1.06 ± 0.16
mise x -- echo 19.8 ± 1.3 18.0 38.9 1.00

mise env

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.6.2 env 19.2 ± 1.1 17.3 26.0 1.00
mise env 21.5 ± 1.0 18.4 26.1 1.12 ± 0.08
⚠️ Inconclusive: env measured 12% slower, but the relative uncertainty overlaps the 10% threshold.

mise hook-env

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.6.2 hook-env 25.4 ± 4.7 19.4 36.8 1.11 ± 0.22
mise hook-env 22.8 ± 1.3 20.1 30.2 1.00
✅ Performance improvement for hook-env is 11%

mise ls

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.6.2 ls 18.4 ± 1.2 15.9 24.0 1.00
mise ls 19.4 ± 1.5 15.9 25.0 1.06 ± 0.11

xtasks/test/perf

Command mise-2026.6.2 mise Variance
install (cached) 155ms 157ms -1%
ls (cached) 71ms 69ms +2%
bin-paths (cached) 80ms 80ms +0%
task-ls (cached) 145ms 148ms -2%

@jdx jdx enabled auto-merge (squash) June 11, 2026 19:04
@jdx jdx merged commit 92a6d8c into main Jun 11, 2026
34 checks passed
@jdx jdx deleted the codex/fix-minimum-release-age-latest branch June 11, 2026 19:14
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.

1 participant