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
8 changes: 8 additions & 0 deletions docs/cli/install.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,13 @@ Like --dry-run but exits with code 1 if there are tools to install

This is useful for scripts to check if tools need to be installed.

### `--include-task-tools`

Also install tools required by tasks in the current scope

This prepares task tools without running task commands or dependencies.
Combine with --monorepo to include tasks from every configured root.

### `--minimum-release-age <MINIMUM_RELEASE_AGE>`

Only install versions released before this date or older than this duration
Expand Down Expand Up @@ -89,4 +96,5 @@ mise install node@20.0.0 # install specific node version
mise install node@20 # install fuzzy node version
mise install node # install version specified in mise.toml
mise install # installs everything specified in mise.toml
mise install --include-task-tools # also install tools required by tasks
```
5 changes: 5 additions & 0 deletions docs/dev-tools/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,11 @@ There are many ways it can be used:
- `mise install node` - install whatever version of node currently specified in `mise.toml` (or other
config files)
- `mise install` - install all plugins and tools specified in the config files
- `mise install --include-task-tools` - also install every tool required by tasks in the current
scope without running those tasks

The last form is useful for warming CI, container, or offline caches before running any task. Add
`--monorepo` to include task tools from every configured monorepo root.

### [`mise exec`|`mise x`](/cli/exec)

Expand Down
4 changes: 4 additions & 0 deletions docs/tasks/task-configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,10 @@ Run [`mise lock`](/dev-tools/mise-lock.html) to resolve task-specific tools into
config's lockfile before running the task. This reads the task definition without executing the
task or installing its tools.

Run `mise install --include-task-tools` to install tools for every task in the current scope without
executing task commands or dependencies. This is useful for preparing CI caches or container images;
combine it with `--monorepo` to include every configured monorepo root.

### `dir`

- **Type**: `string`
Expand Down
15 changes: 15 additions & 0 deletions e2e/cli/test_install_monorepo
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,19 @@ EOF
cat >monorepo/packages/a/mise.toml <<'EOF'
[tools]
tiny = "1.0.0"

[tasks.prepare]
tools.tiny = "3.1.0"
run = "touch task-ran"
EOF
cat >monorepo/packages/b/mise.toml <<'EOF'
[tools]
tiny = "2.1.0"
dummy = "1.0.0"

[tasks.prepare]
tools.dummy = "2.0.0"
run = "touch task-ran"
EOF
echo "2" >monorepo/packages/c/.dummy-version

Expand Down Expand Up @@ -51,6 +59,13 @@ assert_fail "test -d '$MISE_DATA_DIR/installs/tiny/3.1.0'"
assert_fail "test -d '$MISE_DATA_DIR/installs/dummy/1.0.0'"
assert_fail "test -d '$MISE_DATA_DIR/installs/dummy/2.0.0'"

echo "=== install --monorepo --include-task-tools includes every root task ==="
assert "cd monorepo && mise install --monorepo --include-task-tools"
assert "test -d '$MISE_DATA_DIR/installs/tiny/3.1.0'"
assert "test -d '$MISE_DATA_DIR/installs/dummy/2.0.0'"
assert_fail "test -e monorepo/packages/a/task-ran"
assert_fail "test -e monorepo/packages/b/task-ran"

echo "=== ls --monorepo includes every configured root ==="
output=$(cd monorepo && mise ls --monorepo 2>&1)
assert_contains "echo '$output'" "tiny"
Expand Down
123 changes: 123 additions & 0 deletions e2e/cli/test_install_task_tools
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
#!/usr/bin/env bash

set -euo pipefail

rm -rf "$MISE_DATA_DIR/plugins/tiny"
ln -s "$ROOT/test/data/plugins/tiny" "$MISE_DATA_DIR/plugins/tiny"

mkdir -p .mise/tasks
cat >mise.toml <<'EOF'
[tools]
tiny = "1.0.0"

[task_config]
includes = ["tasks.toml", ".mise/tasks"]

[hooks]
preinstall = "printf 'pre\n' >> hooks.log"
postinstall = '''
printf 'post:%s\n' "$MISE_INSTALLED_TOOLS" >> hooks.log
if [ -d "$MISE_DATA_DIR/installs/dummy/1.0.0" ]; then
command -v dummy >postinstall-task-tool-path
fi
'''

[task_templates.with-tools]
tools.tiny = "3.1.0"

[tasks.inline]
hide = true
tools.tiny = "2.1.0"
run = "touch inline-ran"

[tasks.from-template]
extends = "with-tools"
run = "touch template-ran"
EOF

cat >tasks.toml <<'EOF'
[included]
tools.dummy = "1.0.0"
run = "touch included-ran"
EOF

cat >.mise/tasks/file-task <<'EOF'
#!/usr/bin/env bash
#MISE tools.tiny="1.1.0"
touch file-task-ran
EOF
chmod +x .mise/tasks/file-task

# The existing bare install behavior remains limited to configured tools.
mise install
assert "test -d '$MISE_DATA_DIR/installs/tiny/1.0.0'"
assert_fail "test -d '$MISE_DATA_DIR/installs/tiny/1.1.0'"
assert_fail "test -d '$MISE_DATA_DIR/installs/tiny/2.1.0'"
assert_fail "test -d '$MISE_DATA_DIR/installs/tiny/3.1.0'"
assert_fail "test -d '$MISE_DATA_DIR/installs/dummy/1.0.0'"

# Preview every inline, inherited, included, file, and hidden task tool without
# executing a task or changing the install tree.
rm -f hooks.log
output=$(mise install --include-task-tools --dry-run 2>&1)
grep -Fq "tiny@1.1.0" <<<"$output"
grep -Fq "tiny@2.1.0" <<<"$output"
grep -Fq "tiny@3.1.0" <<<"$output"
grep -Fq "dummy@1.0.0" <<<"$output"
assert_fail "test -d '$MISE_DATA_DIR/installs/tiny/1.1.0'"
assert_fail "test -e inline-ran"
assert_fail "test -e template-ran"
assert_fail "test -e included-ran"
assert_fail "test -e file-task-ran"
assert_fail "mise install --include-task-tools --dry-run-code"

mise install --include-task-tools
assert "test -d '$MISE_DATA_DIR/installs/tiny/1.1.0'"
assert "test -d '$MISE_DATA_DIR/installs/tiny/2.1.0'"
assert "test -d '$MISE_DATA_DIR/installs/tiny/3.1.0'"
assert "test -d '$MISE_DATA_DIR/installs/dummy/1.0.0'"
assert "test \"$(grep -c '^pre$' hooks.log)\" -eq 1"
assert "test \"$(grep -c '^post:' hooks.log)\" -eq 1"
assert_contains "cat postinstall-task-tool-path" "$MISE_DATA_DIR/installs/dummy/1.0.0"
assert_fail "test -e inline-ran"
assert_fail "test -e template-ran"
assert_fail "test -e included-ran"
assert_fail "test -e file-task-ran"

# The no-op install path uses the same union for postinstall PATH construction.
rm postinstall-task-tool-path
mise install --include-task-tools
assert_contains "cat postinstall-task-tool-path" "$MISE_DATA_DIR/installs/dummy/1.0.0"

# Explicit tools form a union with task tools rather than filtering them.
rm -rf "$MISE_DATA_DIR/installs/dummy" "$MISE_DATA_DIR/installs/tiny/2.1.0"
mise install dummy@2.0.0 --include-task-tools
assert "test -d '$MISE_DATA_DIR/installs/dummy/1.0.0'"
assert "test -d '$MISE_DATA_DIR/installs/dummy/2.0.0'"
assert "test -d '$MISE_DATA_DIR/installs/tiny/2.1.0'"

# Force applies to the complete union.
touch "$MISE_DATA_DIR/installs/tiny/1.0.0/force-marker"
touch "$MISE_DATA_DIR/installs/tiny/2.1.0/force-marker"
mise install --force --include-task-tools
assert_fail "test -e '$MISE_DATA_DIR/installs/tiny/1.0.0/force-marker'"
assert_fail "test -e '$MISE_DATA_DIR/installs/tiny/2.1.0/force-marker'"

# Conflicting task/config options fail before [plugins] mutates plugin state.
mkdir conflict-plugin
rm -rf "$MISE_DATA_DIR/plugins/conflict-plugin"
cat >mise.toml <<EOF
[plugins]
conflict-plugin = "$PWD/conflict-plugin"

[tools]
conflict-plugin = { version = "1.0.0", flavor = "config" }

[tasks.conflict]
tools.conflict-plugin = { version = "1.0.0", flavor = "task" }
run = "touch conflict-task-ran"
EOF

assert_fail "mise install --include-task-tools"
assert_fail "test -e '$MISE_DATA_DIR/plugins/conflict-plugin'"
assert_fail "test -e conflict-task-ran"
6 changes: 6 additions & 0 deletions man/man1/mise.1
Original file line number Diff line number Diff line change
Expand Up @@ -2445,6 +2445,12 @@ Like \-\-dry\-run but exits with code 1 if there are tools to install

This is useful for scripts to check if tools need to be installed.
.TP
\fB\-\-include\-task\-tools\fR
Also install tools required by tasks in the current scope

This prepares task tools without running task commands or dependencies.
Combine with \-\-monorepo to include tasks from every configured root.
.TP
\fB\-\-minimum\-release\-age\fR \fI<MINIMUM_RELEASE_AGE>\fR
Only install versions released before this date or older than this duration

Expand Down
9 changes: 9 additions & 0 deletions mise.usage.kdl
Original file line number Diff line number Diff line change
Expand Up @@ -1942,6 +1942,7 @@ Examples:
$ mise install node@20 # install fuzzy node version
$ mise install node # install version specified in mise.toml
$ mise install # installs everything specified in mise.toml
$ mise install --include-task-tools # also install tools required by tasks

"""#
flag "-f --force" help=#"""
Expand All @@ -1968,6 +1969,14 @@ This argument will print backend output such as download, configuration, and com
Like --dry-run but exits with code 1 if there are tools to install

This is useful for scripts to check if tools need to be installed.
"""#
}
flag --include-task-tools help="Also install tools required by tasks in the current scope" {
long_help #"""
Also install tools required by tasks in the current scope

This prepares task tools without running task commands or dependencies.
Combine with --monorepo to include tasks from every configured root.
"""#
}
flag --minimum-release-age help="Only install versions released before this date or older than this duration" {
Expand Down
Loading
Loading