Skip to content

fix(npm): respect install_before when resolving dist-tag versions#9145

Merged
jdx merged 6 commits intojdx:mainfrom
webkaz:fix/npm-dist-tag-install-before
Apr 16, 2026
Merged

fix(npm): respect install_before when resolving dist-tag versions#9145
jdx merged 6 commits intojdx:mainfrom
webkaz:fix/npm-dist-tag-install-before

Conversation

@webkaz
Copy link
Copy Markdown
Contributor

@webkaz webkaz commented Apr 16, 2026

Summary

  • When install_before is set (per-tool or global), NPMBackend::latest_stable_version now delegates to latest_version_with_opts (which filters by created_at timestamps) instead of using the dist-tags shortcut that returns the absolute latest version
  • Pre-release versions are already excluded by VERSION_REGEX in fuzzy_match_filter, so the resolved version is always a stable release — same as dist-tags.latest

Fixes #9136

Details

NPMBackend::latest_stable_version overrides the default trait implementation to use npm view <pkg> dist-tags --json. This shortcut ignores install_before date filtering.

The primary install path (mise install) is unaffected because effective_before_date sets ResolveOptions.before_date, and latest_version_with_opts routes through list_versions_matching_with_opts — bypassing latest_stable_version entirely.

However, callers that don't go through effective_before_date — such as mise latest and mise edit — reach latest_stable_version directly. The fix adds a guard that checks per-tool install_before (via config.get_tool_opts) and the global setting, then delegates to the existing date-filtered resolution path.

Note on pre-release versions

The fallback path uses fuzzy_match_filter which excludes pre-release versions (-alpha, -beta, -rc, etc.) via VERSION_REGEX. In the rare case where a package tags a pre-release as latest in dist-tags, the fallback would resolve to the newest stable version instead. This only affects the install_before code path and matches how all other backends handle latest.

Test plan

  • New E2E test e2e/backend/test_npm_install_before: uses mise latest with MISE_INSTALL_BEFORE to verify latest_stable_version respects the date cutoff
  • Existing unit tests pass (cargo test --bin mise backend::npm::tests — 8/8)
  • cargo check passes
  • CI: macOS unit, Windows unit, Windows E2E all pass

Generated with Claude Code

webkaz and others added 4 commits April 16, 2026 22:39
NPMBackend's latest_stable_version used the `npm view dist-tags`
shortcut which returns the absolute latest version without considering
install_before. When install_before is active, fall back to the full
version list with created_at timestamps for proper date-based filtering.

Fixes jdx#9136

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Address code review feedback:
- Clarify comment: this fix catches callers that bypass effective_before_date
  (mise latest, mise edit), not the primary install path
- Add warn! on install_before parse failure instead of silent .ok()
- Add debug! when all versions are filtered out by the cutoff

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Replace inlined filter pipeline with `latest_version_with_opts` which
  already handles date filtering via `list_versions_matching_with_opts`
- Revert `find_match_in_list` to private (no longer needed cross-module)
- Remove unit test that only exercised the generic `filter_by_date` fn
- Make E2E test version extraction consistent between test cases

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The second test case could pass vacuously if mise install fails silently
and installed_ver is empty, since assert_not_contains "" "2.8.8" is true.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings April 16, 2026 16:33
@chatgpt-codex-connector
Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

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 fixes a bug in the NPM backend where the install_before setting was ignored during version resolution because the dist-tags fast path always returned the absolute latest version. The fix involves bypassing this fast path when a date cutoff is configured. Feedback suggests updating the new E2E tests to use the mise latest command directly to ensure the specific code path is exercised, and considering a more generalized fix across other backends that might share this behavior.

Comment thread e2e/backend/test_npm_install_before Outdated
Comment thread e2e/backend/test_npm_install_before Outdated
Comment thread src/backend/npm.rs Outdated
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 updates the npm backend’s “latest stable” resolution so global install_before is respected even in code paths that call latest_stable_version directly (notably mise latest / mise edit), avoiding the dist-tags.latest shortcut which ignores date filtering.

Changes:

  • In NPMBackend::latest_stable_version, detect global Settings::install_before and delegate to latest_version_with_opts with a before_date cutoff.
  • Add a new E2E test intended to cover install_before behavior for the npm backend.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
src/backend/npm.rs Bypasses dist-tags when global install_before is set, routing through date-filtered version resolution.
e2e/backend/test_npm_install_before Adds an E2E regression test around install_before + npm:prettier resolution.

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

Comment thread e2e/backend/test_npm_install_before Outdated
The bug is in NPMBackend::latest_stable_version which is reached by
mise latest / mise edit, not by mise install (which already handles
install_before via effective_before_date). Use mise latest with
MISE_INSTALL_BEFORE env var to test the actual broken code path.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Apr 16, 2026

Greptile Summary

This PR fixes a bug where NPMBackend::latest_stable_version ignored install_before date filtering because it used the dist-tags shortcut, which always returns the absolute latest version. The fix adds a guard that checks both the global Settings::get().install_before and per-tool opts, then delegates to latest_version_with_opts (which filters by created_at timestamps) when a cutoff date is present. An E2E test using mise latest npm:prettier with MISE_INSTALL_BEFORE confirms the regression is resolved.

Confidence Score: 5/5

This PR is safe to merge; the fix is targeted and correct with no regressions on the unfiltered path.

The change is a focused guard in a single method. The date-filtered path (latest_version_with_opts) is the already-tested, existing mechanism used by mise install; this PR just routes mise latest/mise edit into it when install_before is set. The cache bypass is intentional — caching an unfiltered 'absolute latest' would defeat the filter. The E2E test directly exercises the fixed code path with stable historical data. No existing tests are broken, and there are no correctness, data-integrity, or security concerns.

No files require special attention.

Important Files Changed

Filename Overview
src/backend/npm.rs Adds a guard in latest_stable_version to bypass the dist-tags shortcut and delegate to date-filtered path when install_before is set; logic is correct and the cache bypass is intentional.
e2e/backend/test_npm_install_before New E2E regression test using mise latest npm:prettier to verify date-filtered resolution; uses stable historical version dates so the assertions should remain reliable.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["latest_stable_version(config)"] --> B{install_before set?}
    B -- "global Settings or\nper-tool opts" --> C["latest_version_with_opts\n(query=None, before=Some(ts))"]
    B -- "not set" --> D["latest_version_cache (locked)"]
    C --> E["list_versions_matching_with_opts\n(query='latest', before=Some(ts))"]
    E --> F["_list_remote_versions\nnpm view versions time --json"]
    F --> G["VersionInfo::filter_by_date"]
    G --> H["fuzzy_match_filter\nexclude pre-releases via VERSION_REGEX"]
    H --> I["find_match_in_list → last()"]
    D --> J["npm view dist-tags --json\n→ dist_tags['latest']"]
    I --> K["Date-filtered stable version"]
    J --> L["Absolute latest version"]
Loading

Reviews (2): Last reviewed commit: "fix(npm): also check per-tool install_be..." | Re-trigger Greptile

Comment thread src/backend/npm.rs Outdated
@jdx jdx enabled auto-merge (squash) April 16, 2026 16:46
Look up per-tool install_before option from config via get_tool_opts
before falling back to the global setting. This ensures `mise latest`
respects per-tool install_before when set in mise.toml.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
auto-merge was automatically disabled April 16, 2026 16:49

Head branch was pushed to by a user without write access

@webkaz
Copy link
Copy Markdown
Contributor Author

webkaz commented Apr 16, 2026

Thanks @risu729 — updated in ea45fc0. Now checks per-tool install_before via config.get_tool_opts(self.ba()) before falling back to the global setting.

@jdx jdx merged commit 5a4a768 into jdx:main Apr 16, 2026
35 checks passed
risu729 added a commit to risu729/mise that referenced this pull request Apr 17, 2026
The `mise latest` command did not accept a `--before` override, so the CLI
flag could not affect version resolution for stable versions. Per-tool
`install_before` options and the global `install_before` setting were the
only inputs for commands like `mise latest`. Plumb a `--before` flag
through to `latest_version_with_opts`, ensuring the CLI flag takes
precedence and the existing npm `install_before` handling from jdx#9145
continues to work when the flag is omitted.

Made-with: Cursor
mise-en-dev added a commit that referenced this pull request Apr 17, 2026
### 🚀 Features

- **(registry)** add .perl-version support for perl by @ergofriend in
[#9102](#9102)
- **(task)** add Tera template support for inline table run tasks by
@iamkroot in [#9079](#9079)

### 🐛 Bug Fixes

- **(env)** use runtime symlink paths for fuzzy versions by @jdx in
[#9143](#9143)
- **(github)** use full token resolution chain for attestation
verification by @jdx in [#9154](#9154)
- **(go)** Remove install-time version override for subpath packages by
@c22 in [#9135](#9135)
- **(npm)** respect install_before when resolving dist-tag versions by
@webkaz in [#9145](#9145)
- **(self-update)** ensure subcommand exists by @salim-b in
[#9144](#9144)
- **(task)** show available tasks when run target missing by @jdx in
[#9141](#9141)
- **(task)** forward task help args and add raw_args by @jdx in
[#9118](#9118)
- **(task)** remove red/yellow from task prefix colors by
@lechuckcaptain in [#8782](#8782)
- **(task)** merge TOML task block into same-named file task and surface
resolved dir by @jdx in [#9147](#9147)
- **(toolset)** round-trip serialized tool options by @atharvasingh7007
in [#9124](#9124)
- **(vfox)** fallback to absolute bin path if env_keys not set by
@80avin in [#9151](#9151)

### 📚 Documentation

- make agent guide wording generic by @jdx in
[#9142](#9142)

### 📦️ Dependency Updates

- update ghcr.io/jdx/mise:deb docker digest to e019cb9 by @renovate[bot]
in [#9160](#9160)
- update ghcr.io/jdx/mise:copr docker digest to 8d25608 by
@renovate[bot] in [#9159](#9159)
- update ghcr.io/jdx/mise:rpm docker digest to 22e52da by @renovate[bot]
in [#9161](#9161)
- update ghcr.io/jdx/mise:alpine docker digest to a3da97c by
@renovate[bot] in [#9158](#9158)
- update rust docker digest to 4a2ef38 by @renovate[bot] in
[#9162](#9162)
- update ubuntu:24.04 docker digest to c4a8d55 by @renovate[bot] in
[#9164](#9164)
- update rust crate aws-lc-rs to v1.16.3 by @renovate[bot] in
[#9165](#9165)
- update ubuntu docker tag to resolute-20260413 by @renovate[bot] in
[#9169](#9169)
- update rust crate clap to v4.6.1 by @renovate[bot] in
[#9166](#9166)
- update taiki-e/install-action digest to a2352fc by @renovate[bot] in
[#9163](#9163)
- update rust crate ctor to 0.10 by @renovate[bot] in
[#9170](#9170)
- update rust crate tokio to v1.52.1 by @renovate[bot] in
[#9167](#9167)
- update rust crate rmcp-macros to 0.17 by @renovate[bot] in
[#9173](#9173)
- update rust crate signal-hook to 0.4 by @renovate[bot] in
[#9177](#9177)
- update rust crate zipsign-api to 0.2 by @renovate[bot] in
[#9180](#9180)
- update rust crate toml_edit to 0.25 by @renovate[bot] in
[#9179](#9179)
- update rust crate strum to 0.28 by @renovate[bot] in
[#9178](#9178)

### 📦 Registry

- add ibmcloud by @dnwe in
[#9139](#9139)
- add rush by @jdx in [#9146](#9146)

### New Contributors

- @80avin made their first contribution in
[#9151](#9151)
- @atharvasingh7007 made their first contribution in
[#9124](#9124)
- @lechuckcaptain made their first contribution in
[#8782](#8782)
- @ergofriend made their first contribution in
[#9102](#9102)
- @dnwe made their first contribution in
[#9139](#9139)

## 📦 Aqua Registry Updates

#### New Packages (3)

-
[`controlplaneio-fluxcd/flux-operator`](https://github.com/controlplaneio-fluxcd/flux-operator)
-
[`dependency-check/DependencyCheck`](https://github.com/dependency-check/DependencyCheck)
- [`kiro.dev/kiro-cli`](https://github.com/kiro.dev/kiro-cli)

#### Updated Packages (2)

-
[`jreleaser/jreleaser/standalone`](https://github.com/jreleaser/jreleaser/standalone)
- [`sigstore/cosign`](https://github.com/sigstore/cosign)
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.

4 participants