Skip to content

fix(link): reject selector-style link requests - #11218

Merged
jdx merged 1 commit into
jdx:mainfrom
risu729:agent/link-reject-selector-requests
Jul 28, 2026
Merged

jdx merged 1 commit into
jdx:mainfrom
risu729:agent/link-reject-selector-requests

Conversation

@risu729

@risu729 risu729 commented Jul 23, 2026 •

Copy link
Copy Markdown
Contributor

This breaks mise link node@latest or similar. It didn't work well before this PR, but if you prefer to keep them, I'll create another PR to fix it somehow (idk if we can).

Summary

  • allow mise link only for concrete version identities and explicit refs
  • reject prefix, path, sub-tool, system, latest, configured version aliases, and backend-declared rolling channels before filesystem mutation
  • load configuration before resolving configured backend aliases, then refresh only backend/install-state caches after linking so configuration is evaluated once
  • cover rejected selectors, aliases, rolling channels, configured backend aliases, and no-link side effects in the link E2E test

Why

A link creates a named managed install. Resolution selectors such as prefixes, paths, sub-tools, system, latest, aliases, and rolling channels do not identify a stable install pathname; accepting them can create links that later commands cannot address consistently.

Refs remain supported through their normalized ref pathname, and arbitrary literal labels such as brew remain supported when they are not aliases or backend-declared moving channels.

Breaking changes

mise link previously accepted request-style selectors and moving names even though the resulting link did not reliably round-trip through later resolution. These commands now fail before creating or replacing a filesystem link:

mise link node@latest /opt/node
mise link tiny@prefix:9 ./tiny
mise link tiny@path:./tiny ./tiny
mise link tiny@sub-0:9 ./tiny
mise link tiny@system ./tiny
mise link zig@master ./zig       # backend-declared rolling channel
mise link tiny@lts ./tiny        # when `lts` is a configured version alias

For example, latest is also the name of mise's managed runtime symlink. Previously, forcing a link at that name could replace the pointer and then break installed-version resolution:

mise install node@22.17.0
readlink "$MISE_DATA_DIR/installs/node/latest"
# ./22.17.0

mise link --force node@latest /opt/node-dev
readlink "$MISE_DATA_DIR/installs/node/latest"
# /opt/node-dev

mise where node@latest
# error: mise interprets the target basename `node-dev` as a concrete version
# and looks for `$MISE_DATA_DIR/installs/node/node-dev` instead of `/opt/node-dev`

This also prevents mise from updating its normal latest pointer when newer concrete versions are installed.

Use a concrete version, an explicit ref, or an unconfigured stable label instead:

mise link node@22.17.0 /opt/node
mise link node@ref:my-build /opt/node
mise link node@external /opt/node
mise use node@external

Existing links are not removed by this change; it only rejects new mise link invocations that use non-concrete requests.

Testing

  • /usr/bin/mise run test:e2e e2e/cli/test_link
  • /usr/bin/mise run lint-fix
  • hk check src/cli/link.rs e2e/cli/test_link

Summary by CodeRabbit

  • Bug Fixes
    • mise link now rejects non-concrete selectors and unsupported version/ref requests with a clear constraint error.
    • Prevents creation of invalid install entries, including cases like latest that can’t resolve to a fixed target.
    • Backend-alias linking now produces the expected install symlinks for concrete versions, and existing valid links aren’t recreated unnecessarily.
  • Tests
    • Extended CLI end-to-end coverage to verify invalid link attempts don’t change existing install-link sets and to confirm alias-based linking behavior.

@coderabbitai

coderabbitai Bot commented Jul 23, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

mise link now rejects selector-style requests, resolves concrete backend aliases, resets backend state after linking, and adds end-to-end coverage for invalid requests and alias linking.

Changes

Link validation and alias handling

Layer / File(s) Summary
Link validation and pathname resolution
src/cli/link.rs
mise link accepts only concrete versions and refs, rejects latest, unresolved aliases, and rolling channels, resolves backend aliases, derives link pathnames, and resets backend state after linking.
Selector and alias end-to-end coverage
e2e/cli/test_link
Tests verify rejected requests do not create or alter install links, while concrete backend-alias linking creates the expected symlink.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant Link_run
  participant Backend
  participant Filesystem
  User->>Link_run: request tool link
  Link_run->>Link_run: validate concrete version or ref
  Link_run->>Backend: resolve backend alias
  Link_run->>Filesystem: create expected symlink
  Link_run->>Backend: reset backend state
Loading

Possibly related PRs

  • jdx/mise#11172: Both update mise link and its end-to-end coverage for rejecting non-concrete requests.
  • jdx/mise#11207: Both modify Link::run link-path and state-handling behavior.

Suggested reviewers: marukome0743

Poem

A rabbit links paths with a hop and a cheer,
While fuzzy requests are turned away clear.
Aliases resolve, concrete versions align,
And backend state resets in a neat little line.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
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.
Title check ✅ Passed The title clearly matches the main change: rejecting selector-style link requests in mise link.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@greptile-apps

greptile-apps Bot commented Jul 23, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

Updates mise link validation and cache refresh behavior.

  • Rejects selector-style, aliased, rolling-channel, and non-version link requests before filesystem mutation.
  • Preserves concrete versions and explicit refs.
  • Adds end-to-end coverage for accepted and rejected link requests and verifies rejected requests have no link side effects.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failures remain within the scope of this follow-up review.

Important Files Changed

Filename Overview
src/cli/link.rs Adds pre-mutation request validation, loads configuration for alias resolution, and refreshes backend/install-state caches after linking.
e2e/cli/test_link Extends link coverage for selector rejection, alias and rolling-channel handling, backend aliases, and filesystem side effects.

Reviews (4): Last reviewed commit: "fix(link): reject selector-style link re..." | Re-trigger Greptile

@risu729
risu729 force-pushed the agent/link-reject-selector-requests branch from c06bc9e to 5b6979f Compare July 23, 2026 18:39

@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: 1

🤖 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/cli/link.rs`:
- Around line 36-46: Update the Version/Ref match in the link flow to reject
unqualified Version requests such as latest, LTS, or channel names before
constructing ToolVersion, while preserving support for truly explicit versions
and refs. Use the existing ToolRequest version metadata or validation helpers to
distinguish qualified versions; keep the current bail behavior for unsupported
requests and add separate Ref handling only if unqualified references are
intentionally supported.
🪄 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: Central YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: 89cc7c49-692e-49b7-ab6c-ef405fc5c808

📥 Commits

Reviewing files that changed from the base of the PR and between c06bc9e and 5b6979f.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (7)
  • Cargo.toml
  • e2e/backend/test_aqua_failed_install_cleanup
  • e2e/cli/test_link
  • src/backend/mod.rs
  • src/cli/link.rs
  • src/file.rs
  • src/toolset/install_state.rs
🚧 Files skipped from review as they are similar to previous changes (5)
  • e2e/backend/test_aqua_failed_install_cleanup
  • Cargo.toml
  • src/file.rs
  • e2e/cli/test_link
  • src/backend/mod.rs

Comment thread src/cli/link.rs Resolved
@github-actions

Copy link
Copy Markdown
Contributor

This PR currently has merge conflicts. If this continues for 7 days, it will be closed automatically.

This is warning day 1 of 7.

Please update the PR when you have a chance. Feel free to reopen or create a new PR if it is closed and you'd like to continue working on it.

This comment was generated by an automated workflow.

@github-actions

Copy link
Copy Markdown
Contributor

This PR currently has merge conflicts. If this continues for 7 days, it will be closed automatically.

This is warning day 2 of 7.

Please update the PR when you have a chance. Feel free to reopen or create a new PR if it is closed and you'd like to continue working on it.

This comment was generated by an automated workflow.

@risu729
risu729 force-pushed the agent/link-reject-selector-requests branch from 5b6979f to 6e96c57 Compare July 28, 2026 00:53

@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: 1

🤖 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 `@e2e/cli/test_link`:
- Around line 60-66: Extend the rejected-request cases in the CLI link tests to
verify each corresponding install path is absent and not a symlink after the
command fails. Add checks for prefix, path, sub-tool, system, and tiny@latest
requests, matching the existing zig@master absence assertion and using each
request’s expected install location.
🪄 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: Central YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: 33547531-eb72-4abe-a7e0-a968eb6fcef3

📥 Commits

Reviewing files that changed from the base of the PR and between 5b6979f and 6e96c57.

📒 Files selected for processing (1)
  • e2e/cli/test_link

Comment thread e2e/cli/test_link Resolved
@risu729
risu729 force-pushed the agent/link-reject-selector-requests branch from 6e96c57 to fa0457e Compare July 28, 2026 01:09
@risu729
risu729 marked this pull request as ready for review July 28, 2026 01:32
@jdx
jdx merged commit ff49c3d into jdx:main Jul 28, 2026
34 checks passed
@risu729
risu729 deleted the agent/link-reject-selector-requests branch July 28, 2026 03:40
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