Thanks to visit codestin.com
Credit goes to github.com

Skip to content

fix(task): prefer exact task name over extension-stripped match#10393

Merged
jdx merged 1 commit into
jdx:mainfrom
JamBalaya56562:fix-task-exact-match-precedence
Jun 13, 2026
Merged

fix(task): prefer exact task name over extension-stripped match#10393
jdx merged 1 commit into
jdx:mainfrom
JamBalaya56562:fix-task-exact-match-precedence

Conversation

@JamBalaya56562

@JamBalaya56562 JamBalaya56562 commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

Problem

A TOML task whose file points at a script in an auto-discovered file-task dir runs the script twice, concurrently. Reported in #10298:

# mise.toml
[tasks.hello]
file = "mise-tasks/hello.sh"
$ mise run hello
[hello] $ .../mise-tasks/hello.sh
[hello.sh] $ .../mise-tasks/hello.sh
[hello.sh] hi
[hello] hi

Root cause

Scripts in mise-tasks/ are auto-discovered as file tasks named with their extension (hello.sh), while [tasks.hello] is a separate task named hello. They don''t collide, so both exist. GetMatchingExt::get_matching then matched the pattern hello against both, because it treated an exact name match and an extension-stripped match (hello.shhello) with equal precedence — so both tasks ran.

Fix

Run an exact-match pass first, and only fall back to extension-stripped matches when nothing matched exactly. This applies to both code paths in get_matching:

  • the simple-name branch (mise run hello), and
  • the monorepo/glob branch (a bare task expands to //pkg:hello, so //pkg:hello must not also pull in //pkg:hello.sh). The per-entry match was factored into a small closure run in two passes (exact, then extension-stripped fallback).

The extension-stripped fallback is preserved, so mise run build still resolves a build.js file task when no exact build task exists (and the existing e2e/tasks/test_task_monorepo_file_tasks cases — running monorepo file tasks with and without their extension — keep working). Path matching and * wildcard patterns are unchanged.

Testing

  • Unit tests: exact-first precedence for the simple-name form (hello vs hello.sh) and the monorepo form (//pkg:hello vs //pkg:hello.sh), plus the extension-stripped fallback when no exact match exists.
  • New e2e e2e/tasks/test_task_file_toml_no_double_run: asserts mise run hello runs the script exactly once and the [hello.sh] file task does not also run.
  • cargo fmt --all -- --check passes.

Addresses #10298

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • Fixed task resolution to prioritize exact task name matches over file-based auto-discovered tasks, preventing unintended duplicate task execution.
  • Tests

    • Added regression test for task file matching behavior.

When a TOML task and an auto-discovered file task differ only by extension -- e.g.
`[tasks.hello] file = "mise-tasks/hello.sh"` alongside the discovered file task
`hello.sh` -- `mise run hello` matched both (the matcher treated an exact name and
an extension-stripped name as equal precedence) and ran the script twice
concurrently.

In GetMatchingExt::get_matching, run an exact-match pass first and only fall back
to extension-stripped matches when nothing matched exactly. This applies to both
the simple-name branch and the monorepo/glob branch (so `//pkg:hello` is likewise
not joined by `//pkg:hello.sh`). `mise run build` still resolves a `build.js` file
task when no exact "build" task exists.

Addresses discussion jdx#10298.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
@coderabbitai

coderabbitai Bot commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 529fa4f0-7c19-4512-972b-4139768f30b0

📥 Commits

Reviewing files that changed from the base of the PR and between e420ad4 and 99b058b.

📒 Files selected for processing (2)
  • e2e/tasks/test_task_file_toml_no_double_run
  • src/task/mod.rs

📝 Walkthrough

Walkthrough

This PR fixes a task resolution bug where a TOML-defined task could simultaneously match auto-discovered file-task scripts with different extensions. The core algorithm now prefers exact task-key matches over extension-stripped matches, with fallback behavior preserved for cases where no exact match exists (e.g., resolving build to build.js). Changes include the refactored matching logic and comprehensive test coverage.

Changes

Task Matching Priority Fix

Layer / File(s) Summary
Task matching algorithm refactor
src/task/mod.rs
Refactors get_matching to perform an exact-match pass first (no extension stripping) and immediately return if results exist; only on empty results does it allow extension-stripped matching. Introduces an entry_matches closure parameterized by allow_ext_strip to centralize match filtering logic for both simple patterns and monorepo patterns.
Regression test coverage
src/task/mod.rs, e2e/tasks/test_task_file_toml_no_double_run
Adds unit tests asserting exact-match preference over extension-stripped matching for both plain task names (hello vs hello.sh) and monorepo patterns (//pkg:hello vs //pkg:hello.sh), plus an E2E test verifying a TOML-defined task runs exactly once without concurrent auto-discovered file-task execution.

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly Related PRs

  • jdx/mise#10342: Updates task validation to use parent-relative resolved matching logic; shares direct dependency on the same get_matching and task pattern resolution infrastructure modified in this PR.

Poem

🐰 A task named hello now stands proud and clear,
No longer does hello.sh interfere!
Exact matches first, extensions second best,
Our get_matching logic passes every test.
Extension fallback lives on, just in case,
Bug #10298 vanishes without a trace! 🎉

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: preferring exact task name matches over extension-stripped matches, which directly addresses the bug fixed in this PR.
Docstring Coverage ✅ Passed Docstring coverage is 80.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.

✏️ 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.

@greptile-apps

greptile-apps Bot commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Fixes a double-run regression (#10298) where mise run hello would execute a script twice when a TOML task hello and an auto-discovered file task hello.sh both pointed at the same script. The root cause was that GetMatchingExt::get_matching gave equal precedence to exact name matches and extension-stripped matches, so both tasks were selected.

  • Simple-name branch: added an exact-match pre-pass that returns immediately when any task key equals the pattern verbatim; the extension-stripped scan only runs when the pre-pass finds nothing.
  • Monorepo/glob branch: refactored the per-entry predicate into an entry_matches(k, allow_ext_strip) closure, then runs it twice — first with allow_ext_strip = false (exact), falling back to allow_ext_strip = true (extension-stripped) only when the exact pass is empty.
  • Two unit tests and one new e2e test (test_task_file_toml_no_double_run) guard both the fix and the extension-stripped fallback path.

Confidence Score: 5/5

The change is narrowly scoped to the task-matching logic and preserves all pre-existing behaviour; the extension-stripped fallback path, wildcard patterns, and monorepo path matching are all unchanged.

Both touched branches of get_matching are covered by dedicated unit tests and a new end-to-end test. Edge cases (only-file-task fallback, wildcard * task globs, monorepo relative patterns) are exercised. The double-iteration overhead in the fallback path is negligible.

No files require special attention.

Important Files Changed

Filename Overview
src/task/mod.rs Two-pass exact-before-extension-stripped matching in get_matching for both simple-name and monorepo branches; the entry_matches closure correctly gates extension-stripping behind the allow_ext_strip flag and is only invoked twice in the fallback path.
e2e/tasks/test_task_file_toml_no_double_run New regression test for #10298; sets up both a TOML [tasks.hello] and an auto-discovered hello.sh file task, then asserts the script runs exactly once and the [hello.sh] header never appears in output.

Reviews (1): Last reviewed commit: "fix(task): prefer exact task name over e..." | Re-trigger Greptile

@jdx jdx merged commit db6bd8f into jdx:main Jun 13, 2026
33 checks passed
@JamBalaya56562 JamBalaya56562 deleted the fix-task-exact-match-precedence branch June 13, 2026 13:35
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