Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 46 additions & 1 deletion docs/dev-tools/backends/forgejo.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ mise install forgejo:user/repo
```

::: tip
The autodetection logic is implemented in [`src/backend/asset_matcher.rs`](https://github.com/jdx/mise/blob/main/src/backend/asset_matcher.rs), which is shared by the Forgejo, GitHub and GitLab backends.
The autodetection logic is implemented in [`src/backend/asset_matcher.rs`](https://github.com/jdx/mise/blob/main/src/backend/asset_matcher.rs), which is shared by the GitHub, GitLab, and Forgejo backends.
:::

### `asset_pattern`
Expand All @@ -151,6 +151,51 @@ Specifies the pattern to match against release asset names. This is useful when
"forgejo:user/repo" = { version = "latest", asset_pattern = "tool_*_linux_x64.tar.gz" }
```

### `matching`

Narrows asset selection to names containing the given substring, **while keeping platform autodetection**. Unlike [`asset_pattern`](#asset_pattern) (which replaces autodetection entirely), `matching` only refines the candidate set — autodetection still chooses the correct OS/arch from the narrowed list, so a single config stays portable across platforms.

This is the option to reach for when a repository ships **multiple binaries as separate per-platform assets** and autodetection can't tell which one you want.

```toml
[tools]
# When a release ships several binaries per platform (e.g. `mytool-cli` and
# `mytool-server`), matching picks one on every OS/arch without hardcoding a
# platform-specific asset_pattern.
"forgejo:user/repo" = { version = "latest", matching = "mytool-cli" }
```

Tool options can also be passed inline on the command line using `[key=value]` syntax:

```sh
mise use "forgejo:user/repo[matching=mytool-cli]"
```

`matching` is a case-sensitive substring test, so a value that is also a substring of another asset's name (e.g. `matching = "tool"` when both `tool-*` and `tool-extras-*` are published) won't uniquely select your binary. Use [`matching_regex`](#matching_regex) with an anchor when you need a precise match.

If [`asset_pattern`](#asset_pattern) is also set, it takes precedence and `matching`/`matching_regex` are ignored — `asset_pattern` replaces autodetection entirely, so there is no candidate set left for them to narrow. They are ignored silently: when `asset_pattern` is set, a `matching_regex` is never consulted and an invalid one is not reported, since mise does not error on a superseded option.

### `matching_regex`

Like [`matching`](#matching), but the asset name must match the given regular expression. Use this when a substring isn't selective enough. The match is case-sensitive; use an inline `(?i)` flag for case-insensitive matching.

```toml
[tools]
"forgejo:user/repo" = { version = "latest", matching_regex = "^mytool-cli-" }
```

If both `matching` and `matching_regex` are set, an asset must satisfy **both** (logical AND)
to remain a candidate.

::: warning
`matching`/`matching_regex` are **not** part of the install path — it is keyed by the tool
name (`user/repo`, or a `tool_alias`) and version. To install two binaries from the same
release, give each its own [`tool_alias`](/dev-tools/backends/github.html#multiple-assets-from-the-same-release)
so they get distinct install directories; reusing the same `forgejo:user/repo` string with
different `matching` values resolves to the same directory and the second install overwrites
the first.
:::

### `version_prefix`

Specifies a custom version prefix for release tags. By default, mise handles the common `v` prefix (e.g., `v1.0.0`), but some repositories use different prefixes like `release-`, `version-`, or no prefix at all.
Expand Down
90 changes: 85 additions & 5 deletions docs/dev-tools/backends/github.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ mise install github:user/repo
```

::: tip
The autodetection logic is implemented in [`src/backend/asset_matcher.rs`](https://github.com/jdx/mise/blob/main/src/backend/asset_matcher.rs), which is shared by both the GitHub and GitLab backends.
The autodetection logic is implemented in [`src/backend/asset_matcher.rs`](https://github.com/jdx/mise/blob/main/src/backend/asset_matcher.rs), which is shared by the GitHub, GitLab, and Forgejo backends.
:::

### `asset_pattern`
Expand All @@ -56,6 +56,45 @@ Specifies the pattern to match against release asset names. This is useful when
"github:cli/cli" = { version = "latest", asset_pattern = "gh_*_linux_x64.tar.gz" }
```

### `matching`

Narrows asset selection to names containing the given substring, **while keeping platform autodetection**. Unlike [`asset_pattern`](#asset_pattern) (which replaces autodetection entirely), `matching` only refines the candidate set — autodetection still chooses the correct OS/arch from the narrowed list, so a single config stays portable across platforms.

This is the option to reach for when a repository ships **multiple binaries as separate per-platform assets** and autodetection can't tell which one you want (see [Multiple Assets from the Same Release](#multiple-assets-from-the-same-release)).

```toml
[tools]
# oxc-project/oxc ships both oxlint and oxfmt per platform; matching picks oxlint
# on every OS/arch without hardcoding a platform-specific asset_pattern.
# `apps_v1.69.0` is the literal release tag; the assets are per-platform
# archives, and rename_exe renames the extracted `oxlint-<triple>` binary to `oxlint`.
"github:oxc-project/oxc" = { version = "apps_v1.69.0", matching = "oxlint", rename_exe = "oxlint" }
```

Tool options can also be passed inline on the command line using `[key=value]` syntax:

```sh
mise use "github:oxc-project/oxc[matching=oxlint,rename_exe=oxlint]@apps_v1.69.0"
```

`matching` is a case-sensitive substring test, so a value that is also a substring of another asset's name (e.g. `matching = "tool"` when both `tool-*` and `tool-extras-*` are published) won't uniquely select your binary. Use [`matching_regex`](#matching_regex) with an anchor when you need a precise match.

If [`asset_pattern`](#asset_pattern) is also set, it takes precedence and `matching`/`matching_regex` are ignored — `asset_pattern` replaces autodetection entirely, so there is no candidate set left for them to narrow. They are ignored silently: when `asset_pattern` is set, a `matching_regex` is never consulted and an invalid one is not reported, since mise does not error on a superseded option.

The filter also scopes verification: checksums are looked up for the selected asset, and SLSA provenance discovery is narrowed the same way, so a multi-binary release can't verify one binary against another's provenance. A single shared provenance file that attests every artifact in the release (e.g. `multiple.intoto.jsonl`) is still used as a fallback when no per-binary provenance matches.

### `matching_regex`

Like [`matching`](#matching), but the asset name must match the given regular expression. Use this when a substring isn't selective enough. The match is case-sensitive; use an inline `(?i)` flag for case-insensitive matching.

```toml
[tools]
"github:oxc-project/oxc" = { version = "apps_v1.69.0", matching_regex = "^oxlint-", rename_exe = "oxlint" }
```

If both `matching` and `matching_regex` are set, an asset must satisfy **both** (logical AND)
to remain a candidate.

### `version_prefix`

Specifies a custom version prefix for release tags. By default, mise handles the common `v` prefix (e.g., `v1.0.0`), but some repositories use different prefixes like `release-`, `version-`, or no prefix at all.
Expand Down Expand Up @@ -97,14 +136,55 @@ macos-arm64 = { asset_pattern = "gh_*_macOS_arm64.tar.gz" }

The GitHub backend installs one release asset for each tool. If a repository publishes
multiple binaries as separate assets in the same release, define one tool alias per
binary and point each alias at the same `github:owner/repo` backend. Then configure
each aliased tool with its own `asset_pattern`.
binary and point each alias at the same `github:owner/repo` backend, then narrow each
alias to its binary.

Prefer [`matching`](#matching) (or [`matching_regex`](#matching_regex)): it narrows the
candidate set while **keeping platform autodetection**, so one config works on every
OS/arch. This is the right choice when the per-platform asset names can't be templated
portably (e.g. Rust target-triples like `oxlint-aarch64-apple-darwin.tar.gz`).

The example below installs both `oxlint` and `oxfmt` from the single
`oxc-project/oxc` release. Note that each `matching` value must be specific enough to
select **only** the intended binary — if one binary's name were a substring of the
other's, use [`matching_regex`](#matching_regex) with an anchor (e.g. `"^oxlint-"`)
instead (see the [`matching`](#matching) caveat).

```toml
[tool_alias]
tool-a = "github:owner/repo"
tool-b = "github:owner/repo"
oxlint = "github:oxc-project/oxc"
oxfmt = "github:oxc-project/oxc"

[tools.oxlint]
version = "apps_v1.69.0"
matching = "oxlint"
rename_exe = "oxlint"

[tools.oxfmt]
version = "apps_v1.69.0"
matching = "oxfmt"
rename_exe = "oxfmt"
```

::: warning
A distinct alias per binary is **required**, not just tidy. `matching`/`matching_regex` are
**not** part of the install path — it is keyed by the tool name (the alias, or `owner/repo`
when unaliased) and version. Installing the same `github:owner/repo` backend string twice
with different `matching` values (for example `mise use "github:owner/repo[matching=tool-a]"`
followed by `mise use "github:owner/repo[matching=tool-b]"`) resolves to the **same**
directory, so the second install overwrites the first. Giving each binary its own alias gives
each its own install directory, so they coexist.
:::

If the binary isn't named the way you want to invoke it, add
[`rename_exe`](#rename_exe) (renames the executable extracted from an archive) or
[`bin`](#bin) (selects/renames the binary, including a single bare non-archive binary).

Use [`asset_pattern`](#asset_pattern) instead only when you need full manual control and
can name the asset portably (it replaces autodetection, so any `{{os}}`/`{{arch}}`
templating must cover every platform you target):

```toml
[tools.tool-a]
version = "latest"
asset_pattern = "tool-a-*"
Expand Down
47 changes: 46 additions & 1 deletion docs/dev-tools/backends/gitlab.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ mise install gitlab:user/repo
```

::: tip
The autodetection logic is implemented in [`src/backend/asset_matcher.rs`](https://github.com/jdx/mise/blob/main/src/backend/asset_matcher.rs), which is shared by both the GitHub and GitLab backends.
The autodetection logic is implemented in [`src/backend/asset_matcher.rs`](https://github.com/jdx/mise/blob/main/src/backend/asset_matcher.rs), which is shared by the GitHub, GitLab, and Forgejo backends.
:::

### `asset_pattern`
Expand All @@ -147,6 +147,51 @@ version = "latest"
asset_pattern = "gitlab-runner-linux-x64"
```

### `matching`

Narrows asset selection to names containing the given substring, **while keeping platform autodetection**. Unlike [`asset_pattern`](#asset_pattern) (which replaces autodetection entirely), `matching` only refines the candidate set — autodetection still chooses the correct OS/arch from the narrowed list, so a single config stays portable across platforms.

This is the option to reach for when a repository ships **multiple binaries as separate per-platform assets** and autodetection can't tell which one you want.

```toml
[tools]
# When a release ships several binaries per platform (e.g. `mytool-cli` and
# `mytool-server`), matching picks one on every OS/arch without hardcoding a
# platform-specific asset_pattern.
"gitlab:owner/repo" = { version = "latest", matching = "mytool-cli" }
```

Tool options can also be passed inline on the command line using `[key=value]` syntax:

```sh
mise use "gitlab:owner/repo[matching=mytool-cli]"
```

`matching` is a case-sensitive substring test, so a value that is also a substring of another asset's name (e.g. `matching = "tool"` when both `tool-*` and `tool-extras-*` are published) won't uniquely select your binary. Use [`matching_regex`](#matching_regex) with an anchor when you need a precise match.

If [`asset_pattern`](#asset_pattern) is also set, it takes precedence and `matching`/`matching_regex` are ignored — `asset_pattern` replaces autodetection entirely, so there is no candidate set left for them to narrow. They are ignored silently: when `asset_pattern` is set, a `matching_regex` is never consulted and an invalid one is not reported, since mise does not error on a superseded option.

### `matching_regex`

Like [`matching`](#matching), but the asset name must match the given regular expression. Use this when a substring isn't selective enough. The match is case-sensitive; use an inline `(?i)` flag for case-insensitive matching.

```toml
[tools]
"gitlab:owner/repo" = { version = "latest", matching_regex = "^mytool-cli-" }
```

If both `matching` and `matching_regex` are set, an asset must satisfy **both** (logical AND)
to remain a candidate.

::: warning
`matching`/`matching_regex` are **not** part of the install path — it is keyed by the tool
name (`owner/repo`, or a `tool_alias`) and version. To install two binaries from the same
release, give each its own [`tool_alias`](/dev-tools/backends/github.html#multiple-assets-from-the-same-release)
so they get distinct install directories; reusing the same `gitlab:owner/repo` string with
different `matching` values resolves to the same directory and the second install overwrites
the first.
:::

### `version_prefix`

Specifies a custom version prefix for release tags. By default, mise handles the common `v` prefix (e.g., `v1.0.0`), but some repositories use different prefixes like `release-`, `version-`, or no prefix at all.
Expand Down
6 changes: 4 additions & 2 deletions docs/dev-tools/backends/ubi.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
# Ubi Backend <Badge type="danger" text="deprecated" />

::: warning
The ubi backend is **deprecated**. Please use the [github backend](/dev-tools/backends/github) instead.
The ubi backend is **deprecated**. Please use the [GitHub backend](/dev-tools/backends/github) instead.

The github backend offers several advantages over ubi including provenance verification, download progress reports, and fewer dependencies. To migrate, replace `ubi:owner/repo` with `github:owner/repo` in your configuration files.
The GitHub backend offers several advantages over ubi including provenance verification, download progress reports, and fewer dependencies. To migrate, replace `ubi:owner/repo` with `github:owner/repo` in your configuration files. The [`matching`](/dev-tools/backends/github.html#matching) and [`matching_regex`](/dev-tools/backends/github.html#matching_regex) options carry over. One behavioral difference is worth noting: ubi applies the substring `matching` only as a tiebreaker among assets that already match your OS/arch, and skips it when a single asset matches the platform. The GitHub backend applies `matching` as a pre-filter before autodetection, so for multi-binary releases you get the binary your filter names, or a clear error naming the filter if it isn't published for your platform.

One migration gotcha: ubi folds `matching` into the install path, so you can install several binaries from one repo via separate `matching` values on the same `ubi:owner/repo` string. The GitHub backend keeps the install path keyed by tool name + version only, so two `github:owner/repo` entries with different `matching` values resolve to the **same** directory and the second overwrites the first. If you rely on that ubi pattern, give each binary its own [`tool_alias`](/dev-tools/backends/github.html#multiple-assets-from-the-same-release) on GitHub so each gets its own install directory.
:::

You may install GitHub Releases and URL packages directly using [ubi](https://github.com/houseabsolute/ubi) backend. ubi is directly compiled into
Expand Down
52 changes: 52 additions & 0 deletions e2e/backend/test_forgejo_matching
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#!/usr/bin/env bash

# Disabled: Forgejo tests are flaky due to intermittent API issues (same reason
# e2e/backend/test_forgejo is disabled). Kept here, ready to enable, so the forgejo
# `matching`/`matching_regex` path has e2e parity with gitlab the moment the forgejo
# API is reliable enough to re-enable. Until then, the forgejo plumbing is covered by
# the unit test backend::github::tests::test_matching_plumbing_parity_across_git_backends
# (which exercises the Forgejo backend type's option accessors, lockfile serialization,
# and install-time-key inheritance) and by the passing gitlab e2e, which shares the
# same AssetMatcher.
exit 0

# Test the `matching` / `matching_regex` options on the FORGEJO backend.
#
# Mirrors e2e/backend/test_gitlab_matching: forgejo:roele/mise-test-fixtures v1.0.0
# ships THREE assets (fd-8.7.0.tar.gz, hello-world-1.0.0.tar.gz,
# hello-world-2.0.0.tar.gz), none carrying OS/arch tokens, so the shortest-name
# tiebreak picks fd-8.7.0.tar.gz by default. `matching` narrows the candidate set
# BEFORE autodetection, proving the filter changes selection on the SEPARATE
# resolve_forgejo_asset_url_for_target path.

export MISE_EXPERIMENTAL=1

# A matching value that excludes every asset must FAIL asset selection on the
# forgejo path with an error naming the filter — proving `matching` is parsed and
# threaded into resolve_forgejo_asset_url_for_target, not silently ignored. Run
# BEFORE any successful install (install dir is keyed by repo+version, not by the
# matching value, so an installed version would make `mise install` a no-op).
assert_fail 'mise install "forgejo:roele/mise-test-fixtures[matching=does-not-exist]@1.0.0"' "filtered by matching"

# A syntactically invalid matching_regex (unclosed group) must be a hard error on
# the forgejo path, not silently ignored.
assert_fail 'mise install "forgejo:roele/mise-test-fixtures[matching_regex=hello(]@1.0.0"' "invalid matching_regex"

# matching=hello-world narrows to the two hello-world-* assets; the tiebreak picks
# hello-world-1.0.0.tar.gz (NOT the default fd-8.7.0.tar.gz), and it runs.
cat <<EOF >mise.toml
[tools]
"forgejo:roele/mise-test-fixtures" = { version = "1.0.0", matching = "hello-world", bin_path = "hello-world-1.0.0/bin", postinstall = "chmod +x \$MISE_TOOL_INSTALL_PATH/hello-world-1.0.0/bin/hello-world" }
EOF
mise install
assert_contains "mise x -- hello-world" "hello world"
mise uninstall forgejo:roele/mise-test-fixtures

# matching_regex selects on the forgejo path too: ^hello-world-1 matches only
# hello-world-1.0.0.tar.gz.
cat <<EOF >mise.toml
[tools]
"forgejo:roele/mise-test-fixtures" = { version = "1.0.0", matching_regex = "^hello-world-1", bin_path = "hello-world-1.0.0/bin", postinstall = "chmod +x \$MISE_TOOL_INSTALL_PATH/hello-world-1.0.0/bin/hello-world" }
EOF
mise install
assert_contains "mise x -- hello-world" "hello world"
Loading
Loading