Skip to content

Commit e9afca6

Browse files
jdxclaudeautofix-ci[bot]
authored
fix(github): use alias-specific options when tool_alias has its own config (#8892)
## Summary - Fixed regression where `tool_alias` with per-alias `asset_pattern` (or other options) would use the original tool's options instead of the alias-specific ones - Changed `get_tool_opts()` to prefer the alias-specific config entry when it has options set, falling back to the resolved name match for CLI-created requests without options (preserves the treesize/gitlab fix from #8084) - Added e2e test verifying both the original tool and its alias install with their respective asset patterns Fixes #8847 ## Test plan - [x] `cargo test` — all 563 unit tests pass - [x] `mise run test:e2e test_github_tool_alias_asset_pattern` — new e2e test passes - [x] All lint hooks pass 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Changes tool option resolution for aliased backends, which can affect how tools are downloaded/installed (e.g., `asset_pattern`) for some configurations; scope is localized but impacts installation behavior. > > **Overview** > Fixes a regression where a `tool_alias` could incorrectly inherit the original tool’s option set (notably `asset_pattern`) instead of using the alias-specific config. > > `Config::get_tool_opts()` now considers both the alias short-name match and the resolved full-name match and selects the entry that actually has options, preferring the alias-specific entry when present while preserving the fallback for resolved-name configs. > > Adds an e2e regression test that configures a GitHub tool and its alias with different `asset_pattern` values and verifies both install using their respective assets. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 7f9ce83. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
1 parent f326d2f commit e9afca6

File tree

2 files changed

+52
-7
lines changed

2 files changed

+52
-7
lines changed
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#!/usr/bin/env bash
2+
# Test that tool_alias with asset_pattern uses the alias-specific options
3+
# Regression test for https://github.com/jdx/mise/discussions/8847
4+
# When both the original tool and an aliased tool are configured with different
5+
# asset_pattern values, each should use its own pattern.
6+
7+
cat <<'EOF' >mise.toml
8+
[tool_alias]
9+
hw2 = "github:jdx/mise-test-fixtures"
10+
11+
[tools."github:jdx/mise-test-fixtures"]
12+
version = "1.0.0"
13+
asset_pattern = "hello-world-1.0.0.tar.gz"
14+
bin_path = "hello-world-1.0.0/bin"
15+
postinstall = "chmod +x $MISE_TOOL_INSTALL_PATH/hello-world-1.0.0/bin/hello-world"
16+
17+
[tools.hw2]
18+
version = "1.0.0"
19+
asset_pattern = "hello-world-2.0.0.tar.gz"
20+
bin_path = "hello-world-2.0.0/bin"
21+
postinstall = "chmod +x $MISE_TOOL_INSTALL_PATH/hello-world-2.0.0/bin/hello-world"
22+
EOF
23+
24+
mise install
25+
# Both should install successfully with the correct asset
26+
assert_contains "mise x -- hello-world" "hello world"
27+
# The aliased tool should have installed using hello-world-2.0.0.tar.gz
28+
assert "test -d ~/.local/share/mise/installs/hw2/1.0.0/hello-world-2.0.0"

src/config/mod.rs

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -351,17 +351,34 @@ impl Config {
351351
backend_arg: &Arc<BackendArg>,
352352
) -> Result<Option<ToolVersionOptions>> {
353353
let trs = self.get_tool_request_set().await?;
354-
// Try matching by resolved full name first for aliased tools.
354+
let short_match = trs.iter().find(|tr| tr.0.short == backend_arg.short);
355+
// Also try matching by resolved full name for aliased tools.
355356
// e.g., ba.short="treesize" resolves to full="gitlab:FBibonne/treesize"
356357
// while the config entry has short="gitlab-f-bibonne-treesize" with api_url set.
357-
// We check the resolved name first because the direct short match might find
358-
// a CLI-created tool request without options.
359358
let full = backend_arg.full();
360359
let resolved_ba = BackendArg::new(full, None);
361-
let tool_request = trs
362-
.iter()
363-
.find(|tr| tr.0.short == resolved_ba.short)
364-
.or_else(|| trs.iter().find(|tr| tr.0.short == backend_arg.short));
360+
let resolved_match = trs.iter().find(|tr| tr.0.short == resolved_ba.short);
361+
362+
let has_opts = |tr: &(&Arc<BackendArg>, &Vec<crate::toolset::ToolRequest>, _)| -> bool {
363+
tr.1.first()
364+
.is_some_and(|req| !req.options().opts.is_empty())
365+
};
366+
// Prefer whichever match has options set. When both have options,
367+
// prefer the short (alias-specific) match since it's more specific.
368+
// Fall back to the resolved match for cases where a CLI-created
369+
// request without options shadows the config entry (treesize case).
370+
let tool_request = match (short_match, resolved_match) {
371+
(Some(s), Some(r)) => {
372+
if has_opts(&s) {
373+
Some(s)
374+
} else {
375+
Some(r)
376+
}
377+
}
378+
(Some(s), None) => Some(s),
379+
(None, Some(r)) => Some(r),
380+
(None, None) => None,
381+
};
365382
Ok(tool_request.and_then(|tr| tr.1.first().map(|req| req.options())))
366383
}
367384

0 commit comments

Comments
 (0)