Skip to content

fix(mise): ignore mise shims when resolving tools - #1209

Open
iamrz1 wants to merge 2 commits into
mainfrom
fix/dt-5560-find-tool-ignore-mise-shims
Open

iamrz1 wants to merge 2 commits into
mainfrom
fix/dt-5560-find-tool-ignore-mise-shims

Conversation

@iamrz1

@iamrz1 iamrz1 commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

What this PR does / why we need it

make fmt, make lint and make build fail for devbase-managed tools:

mise ERROR No version is set for shim: shfmt

find_tool() resolves tools with command -v, which returns a mise shim when the shims directory is on PATH. mise_exec_tool_with_bin() then runs that shim directly and never reaches its fallback:

run_mise exec "$toolName@$(devbase_tool_version_from_mise "$toolName")" -- "$binName" "$@"

A bare shim resolves its version from the current directory's mise config. devbase tools are declared only in mise.devbase.toml (the devbase env), so there is nothing to resolve.

This skips shim paths so callers fall through to mise exec, mirroring the existing asdf shim handling. mise_shim_dir() sits next to asdf_shim_dir() and honours MISE_SHIMS_DIR.

Affects golangci-lint, shfmt, mage, lintroller, kubeconform, shellcheck, terraform, tombi.

Jira ID

DT-5560

Notes for your reviewers

Not urgent. The user-visible breakage is already mitigated by orc#2034. This is the durable fix, worth landing because --shims bypasses that setting (verified: MISE_NOT_FOUND_AUTO_INSTALL=false mise activate bash --shims still puts shims on PATH; devbase uses that form at shell/lib/mise.sh:62,71), and because the orc mitigation depends on mise continuing to gate shim placement on not_found_auto_install. Suggest letting this propagate through normal stencil upgrades rather than a bulk re-stencil.

CI is not currently broken. devbase_configure_global_tools copies mise.devbase.toml into the user-wide config so CI shims resolve. This makes that workaround unnecessary rather than fixing a live failure.

Trigger: mise v2026.9.0 (2026-09-01) started prepending the shims directory to PATH, ahead of ~/.asdf/shims which previously won this lookup. The defect is older: this code is unchanged since 1141d86 (2026-02-03).

Verification

End to end in gearbox, shims forced onto PATH:

BEFORE (unpatched .bootstrap):  mise ERROR No version is set for shim: shfmt
AFTER  (this branch):           v3.13.1     # matches mise.devbase.toml
case before after
devbase-only (shfmt) returns shim, fails falls through to mise exec
real binary (git) /opt/homebrew/bin/git unchanged
repo-declared (uv, gearbox mise.toml) returns shim resolved install path, 0.11.8

The third row is the regression risk: a tool in the repo's own mise.toml must still resolve. It does, via mise which in the repo directory where that config is active.

bash -n clean; make fmt and make lint pass.

🤖 Generated with Claude Code

find_tool() resolved tools with `command -v`, which returns a mise shim
when the shims directory is on PATH. mise_exec_tool_with_bin() then
executed that shim directly and never reached its fallback,
`mise exec $toolName@$(devbase_tool_version_from_mise $toolName)`.

A bare shim resolves its version from the mise config in the current
directory. devbase-managed tools are declared only in mise.devbase.toml
(the `devbase` env), which is not active for a bare shim call, so the
shim fails with "No version is set for shim: <tool>" and `make fmt`,
`make lint` and `make build` fail for golangci-lint, shfmt, mage,
lintroller, kubeconform, shellcheck, terraform and tombi.

Skip shim paths so callers fall through to the `mise exec` branch, which
resolves the version devbase pins. This mirrors the existing asdf shim
handling. Add mise_shim_dir() alongside asdf_shim_dir(), honouring
MISE_SHIMS_DIR.

Tools declared in a repo's own mise.toml are unaffected: `mise which`
runs in the repo directory where that config is active, and now returns
the resolved install path rather than the shim.

Exposed by mise 2026.9.0, which started prepending the shims directory
to PATH under `mise activate`. The defect predates it: this code has
been unchanged since 1141d86 (2026-02-03) and only failed once
something put shims on PATH. Guarding here rather than relying on mise's
placement means a future change to that behavior cannot break tool
resolution again.

DT-5560

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@iamrz1
iamrz1 requested a review from a team as a code owner September 7, 2026 14:39
Condense the explanatory comments to the essentials; the detail belongs
in the commit message and DT-5560, not inline.

DT-5560

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@getoutreach-ci-2

Copy link
Copy Markdown

Link to code coverage report (posted by coverbot 🤖)

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

Two notes, neither blocking.

1. Scope vs the ticket's acceptance criteria. DT-5560 asks that devbase-managed tools resolve to the versions pinned in mise.devbase.toml. This stops shims winning, but a real binary still wins: a repo carrying golangci-lint = "2.13.2" in customMiseTools, or a Homebrew install, still overrides the pinned 2.9.0 silently. Worth a scope note so the ticket isn't closed on it.

2. The mise not found error branch is unreachable under set -e. Pre-existing, but this PR moves the code out of the if so it runs on every shim hit. One-line fix inline.

🤖 Generated with Claude Code

Comment thread shell/lib/mise.sh
toolPath="$(command -v "$toolName" 2>/dev/null)"
# Skip mise shims: they resolve versions from the current directory's config,
# which doesn't declare devbase tools. Callers fall through to `mise exec`.
if [[ -n $toolPath ]] && [[ $toolPath != "$(mise_shim_dir)"/* ]]; then

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This line decides the scope of the fix: a shim falls through to mise exec, anything else runs as-is. So a real binary still beats devbase's pin. A repo carrying golangci-lint = "2.13.2" in customMiseTools, or a Homebrew install, produces a non-shim path here and runs instead of the pinned 2.9.0, with no error.

Right for a repo's own tools (your uv row), wrong for devbase-pinned ones, and find_tool can't tell them apart. Not for this PR, but DT-5560's acceptance criteria ask for exactly this, so a scope note and a follow-up would help.

Comment thread shell/lib/mise.sh
fi

local misePath
misePath="$(find_mise)"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

find_mise returns 1 when mise is absent, so under set -e this assignment aborts before line 306 ever runs, making the mise not found (find_tool) error unreachable.

Pre-existing, but it matters a bit more now: this block used to run only when command -v missed, and now it also runs on every mise shim hit. The version proposed on the ticket had || true here.

Suggested change
misePath="$(find_mise)"
misePath="$(find_mise)" || true

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