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
1 change: 1 addition & 0 deletions docs/.vitepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ export default withMermaid(
{ text: "File Tasks", link: "/tasks/file-tasks" },
{ text: "Task Arguments", link: "/tasks/task-arguments" },
{ text: "Task Configuration", link: "/tasks/task-configuration" },
{ text: "Task Templates", link: "/tasks/templates" },
{ text: "Monorepo Tasks", link: "/tasks/monorepo" },
],
},
Expand Down
2 changes: 1 addition & 1 deletion docs/tasks/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Here's my favorite features about mise's task runner:
- ability to write tasks as actual bash script files and not inside yml/json/toml strings that lack
syntax highlighting and linting/checking support

There are 2 ways to define tasks: [inside of `mise.toml` files](./toml-tasks.html) or as [standalone shell scripts](./file-tasks.html).
There are 2 ways to define tasks: [inside of `mise.toml` files](./toml-tasks.html) or as [standalone shell scripts](./file-tasks.html). You can also use [task templates](./templates.html) to create reusable task definitions.

## Tasks in `mise.toml` files

Expand Down
35 changes: 35 additions & 0 deletions docs/tasks/monorepo.md
Original file line number Diff line number Diff line change
Expand Up @@ -435,8 +435,43 @@ mise's Monorepo Tasks aims to hit the sweet spot between simplicity and power:

The best tool is the one that fits your team's needs. mise's Monorepo Tasks is designed for teams who want powerful monorepo management without the complexity overhead, especially when working across multiple languages.

## Task Templates

For monorepos with similar task patterns across projects, [task templates](/tasks/templates) allow you to define reusable task definitions at the monorepo root:

```toml
# Root mise.toml
[settings]
experimental = true
experimental_monorepo_root = true

[task_templates."python:build"]
run = "uv build"
tools = { python = "3.12", uv = "latest" }

[task_templates."python:test"]
run = "pytest"
tools = { python = "3.12" }
depends = ["build"]
```

Projects can then extend these templates:

```toml
# packages/api/mise.toml
[tasks.build]
extends = "python:build"

[tasks.test]
extends = "python:test"
run = "pytest --cov" # Override with coverage
```

See [Task Templates](/tasks/templates) for complete documentation.

## Related

- [Task Templates](/tasks/templates) - Reusable task definitions
- [Task Configuration](/tasks/task-configuration) - All task configuration options
- [Running Tasks](/tasks/running-tasks) - How to execute tasks
- [Configuration](/configuration) - General mise configuration
178 changes: 178 additions & 0 deletions docs/tasks/templates.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
# Task Templates

::: warning
This feature is experimental and requires `experimental = true` in your settings.
:::

Task templates allow you to define reusable task definitions that can be extended by multiple tasks. This is particularly useful in monorepos or projects with similar task patterns across different components.

## Defining Templates

Templates are defined in the `[task_templates.*]` section of your `mise.toml`:

```toml
[settings]
experimental = true

[task_templates."python:build"]
description = "Build a Python project"
run = "uv build"
tools = { python = "3.12", uv = "latest" }
env = { PYTHONPATH = "src" }

[task_templates."python:test"]
description = "Run Python tests"
run = "pytest"
tools = { python = "3.12" }
depends = ["build"]
```

## Extending Templates

Tasks can extend templates using the `extends` field:

```toml
[tasks.build]
extends = "python:build"

[tasks.test]
extends = "python:test"
run = "pytest --cov" # Override run while keeping tools, depends
```

## Template Naming

Templates use colon (`:`) separators for namespacing, similar to task naming conventions in monorepos:

- `python:build`
- `python:test`
- `rust:cargo:build`
- `node:npm:test`

## Merge Semantics

When a task extends a template, fields are merged according to these rules:

| Field | Behavior |
| --------------------------------------- | ----------------------------------------------------------- |
| `run`, `run_windows` | Local overrides completely |
| `tools` | Deep merge (local tools added/override template) |
| `env` | Deep merge (local env added/override template) |
| `depends`, `depends_post`, `wait_for` | Local overrides completely (not merged) |
| `dir` | Local overrides; defaults to config_root if not in template |
| `sources`, `outputs` | Local overrides completely |
| `description`, `shell`, `timeout`, etc. | Local overrides template (if set) |
| `quiet`, `hide`, `raw` | Not inherited (must be set explicitly in task) |

### Example: Deep Merge for Tools

```toml
[task_templates."fullstack:build"]
tools = { python = "3.12", node = "18" }

[tasks.build]
extends = "fullstack:build"
tools = { node = "20" } # Override node, keep python from template
# Result: tools = { python = "3.12", node = "20" }
```

### Example: Deep Merge for Env

```toml
[task_templates."python:build"]
env = { PYTHONPATH = "src", DEBUG = "0" }

[tasks.build]
extends = "python:build"
env = { DEBUG = "1" } # Override DEBUG, keep PYTHONPATH from template
# Result: env = { PYTHONPATH = "src", DEBUG = "1" }
```

### Example: Complete Override for Depends

```toml
[task_templates."python:test"]
depends = ["lint", "typecheck"]

[tasks.test]
extends = "python:test"
depends = ["build"] # Completely replaces template depends
# Result: depends = ["build"] (lint and typecheck NOT included)
```

## Tera Templating

Templates support Tera templating, rendered with the **using project's context**:

```toml
[task_templates."python:build"]
description = "Build Python project"
dir = "{{ config_root }}" # Resolves to the PROJECT's directory
run = "uv build"
env = { PROJECT = "{{ config_root | basename }}" }
```

Available variables (same as regular tasks):

- <code v-pre>{{ config_root }}</code> - The project using the template (NOT where template is defined)
- <code v-pre>{{ env.VAR }}</code> - Environment variables
- <code v-pre>{{ cwd }}</code> - Current working directory
- <code v-pre>{{ vars.* }}</code> - User-defined variables from config

## Monorepo Usage

Task templates are especially useful in monorepos where multiple packages share similar build patterns:

```toml
# Root mise.toml
[settings]
experimental = true
experimental_monorepo_root = true

[task_templates."python:build"]
run = "uv build"
tools = { python = "3.12", uv = "latest" }

[task_templates."python:test"]
run = "pytest"
tools = { python = "3.12" }
depends = ["build"]

[task_templates."python:lint"]
run = "ruff check ."
tools = { python = "3.12", ruff = "latest" }
```

```toml
# packages/api/mise.toml
[tasks.build]
extends = "python:build"

[tasks.test]
extends = "python:test"
run = "pytest --cov" # Add coverage

[tasks.lint]
extends = "python:lint"
```

```toml
# packages/worker/mise.toml
[tasks.build]
extends = "python:build"

[tasks.test]
extends = "python:test"

[tasks.lint]
extends = "python:lint"
```

## Future Enhancements

The following features are planned for future releases:

- **Global templates**: Define templates in `~/.config/mise/config.toml` for use across all projects
- **Template packages**: Import templates from external sources
- **Pattern-matching rules**: Auto-apply templates based on file detection (e.g., auto-apply `python:*` templates when `pyproject.toml` exists)
- **File task templates**: Define templates as standalone script files, similar to [file tasks](/tasks/file-tasks)
Loading
Loading