Skip to content

feat(task): add task templates for reusable task definitions#7873

Merged
jdx merged 8 commits intomainfrom
feat/task-templates
Jan 28, 2026
Merged

feat(task): add task templates for reusable task definitions#7873
jdx merged 8 commits intomainfrom
feat/task-templates

Conversation

@jdx
Copy link
Copy Markdown
Owner

@jdx jdx commented Jan 28, 2026

Summary

This PR adds support for task templates that allow defining reusable task definitions which can be extended by tasks via the extends field. This enables DRY task definitions in monorepos and projects with similar task patterns.

Key features:

  • Templates are defined in [task_templates.*] sections of mise.toml
  • Tasks can extend templates using extends = "template-name"
  • Templates support colon-namespacing: python:build, rust:test, etc.
  • Smart merge semantics:
    • run, depends, sources, outputs: local overrides completely
    • tools, env: deep merge (local values override template values)
    • Other fields: local overrides if set
  • Requires experimental = true in settings

Example usage:

[settings]
experimental = true

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

[tasks.build]
extends = "python:build"
env = { DEBUG = "1" }  # merged with template env

Test plan

  • E2E test for basic template extension
  • E2E test for local override of run
  • E2E test for tools deep merge
  • E2E test for env deep merge
  • E2E test for description inheritance and override
  • E2E test for depends inheritance and override
  • E2E test for error on missing template
  • E2E test for namespaced template names (colons)
  • E2E test for experimental flag requirement
  • Unit tests for merge logic

🤖 Generated with Claude Code


Note

Adds experimental task templates to enable DRY task definitions and inheritance.

  • New task_templates in mise.toml with extends support and defined merge semantics; implements TaskTemplate and Task::merge_template
  • Task loading pipeline updated to collect/resolve templates across config hierarchy; functions now accept templates and error if missing or if experimental is off
  • generate task-docs updated to include template resolution
  • Docs: new docs/tasks/templates.md, sidebar/nav entries, and monorepo references
  • Tests: comprehensive e2e for extends/merging/errors/namespacing/experimental flag and unit tests for merge logic

Written by Cursor Bugbot for commit d2a9296. This will update automatically on new commits. Configure here.

Add support for task templates that can be extended by tasks via the
`extends` field. This enables DRY task definitions in monorepos and
projects with similar task patterns.

Templates are defined in [task_templates.*] sections and can provide
default values for run, tools, env, depends, and other task fields.
Tasks can extend templates and override specific fields as needed.

Merge semantics:
- run, depends, sources, outputs: local overrides completely
- tools, env: deep merge (local values override template)
- Other fields: local overrides if set

Requires experimental = true to use.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings January 28, 2026 15:05
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds support for task templates, allowing users to define reusable task definitions that can be extended by tasks via the extends field. This feature enables DRY (Don't Repeat Yourself) principles in task definitions, particularly useful in monorepos and projects with similar task patterns.

Changes:

  • Introduces TaskTemplate struct with same fields as Task for defining reusable configurations
  • Implements template resolution with smart merge semantics (deep merge for tools/env, complete override for run/depends/sources/outputs)
  • Adds experimental flag requirement for using the extends feature
  • Templates support colon-namespacing (e.g., python:build, rust:test)

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/task/task_template.rs New file containing TaskTemplate struct and merge_template implementation with comprehensive unit tests
src/task/mod.rs Adds extends field to Task struct and exports TaskTemplate
src/config/mod.rs Implements template collection, resolution, and integration into task loading pipeline
src/config/config_file/mod.rs Adds task_templates() trait method to ConfigFile
src/config/config_file/mise_toml.rs Implements TaskTemplates type and deserialization logic
src/cli/generate/task_docs.rs Updates task documentation generation to handle templates
e2e/tasks/test_task_templates Comprehensive E2E tests covering all template features and edge cases

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

redactions: self.redactions.clone(),
plugins: self.plugins.clone(),
tasks: self.tasks.clone(),
task_templates: self.task_templates.clone(),
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The task_templates field in the Clone implementation lacks test coverage. Consider adding a test that verifies cloning a MiseToml instance with task templates preserves the templates correctly.

Copilot uses AI. Check for mistakes.
Comment thread src/config/mod.rs
Comment on lines +1495 to +1496
// Iterate in reverse order (global -> local) so child directories override parent configs
for cf in config_files.values().rev() {
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment states 'Iterate in reverse order (global -> local) so child directories override parent configs', but .rev() on values() actually iterates from local to global (since values() already returns an iterator in insertion order, which is global->local in ConfigMap). Either the comment is incorrect or the iteration order is backwards. Consider clarifying or fixing this.

Suggested change
// Iterate in reverse order (global -> local) so child directories override parent configs
for cf in config_files.values().rev() {
// Iterate from global to local so later (child) configs overwrite earlier (parent) templates
for cf in config_files.values() {

Copilot uses AI. Check for mistakes.

assert "mise run build" "cargo build"

echo '' >mise.toml
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test cleanup at the end uses echo '' >mise.toml which creates a file with a newline. Consider using rm -f mise.toml or true >mise.toml for cleaner test isolation, as the empty file with a newline could affect subsequent tests.

Suggested change
echo '' >mise.toml
rm -f mise.toml

Copilot uses AI. Check for mistakes.
jdx and others added 5 commits January 28, 2026 09:08
- Add new docs/tasks/templates.md with comprehensive documentation
- Update docs/tasks/index.md to reference templates
- Update docs/tasks/monorepo.md to show template usage in monorepos
- Add Task Templates to sidebar navigation

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Use <code v-pre> to escape Tera template syntax that was being
interpreted as Vue template syntax by VitePress.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@jdx
Copy link
Copy Markdown
Owner Author

jdx commented Jan 28, 2026

bugbot run

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

Comment thread src/task/task_template.rs
Boolean fields (quiet, hide, raw) in Task use `bool` not `Option<bool>`,
so we cannot distinguish between "not set" (defaults to false) and
"explicitly set to false". Remove merge logic for these fields to avoid
overriding a task's explicit `false` value with a template's `true`.

Users must explicitly set these fields in their task if needed.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@jdx jdx enabled auto-merge (squash) January 28, 2026 15:48
@jdx jdx merged commit 81589bd into main Jan 28, 2026
34 checks passed
@jdx jdx deleted the feat/task-templates branch January 28, 2026 15:52
@github-actions
Copy link
Copy Markdown

Hyperfine Performance

mise x -- echo

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.1.8 x -- echo 19.1 ± 0.2 18.6 21.7 1.00
mise x -- echo 19.3 ± 0.2 18.9 20.5 1.01 ± 0.02

mise env

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.1.8 env 18.5 ± 0.5 18.0 23.5 1.00
mise env 18.8 ± 0.3 18.2 22.3 1.02 ± 0.03

mise hook-env

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.1.8 hook-env 18.8 ± 0.3 18.4 24.6 1.00
mise hook-env 19.1 ± 0.2 18.6 20.3 1.01 ± 0.02

mise ls

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.1.8 ls 16.7 ± 0.2 16.2 17.4 1.00
mise ls 17.0 ± 0.2 16.5 19.0 1.02 ± 0.02

xtasks/test/perf

Command mise-2026.1.8 mise Variance
install (cached) 108ms 108ms +0%
ls (cached) 65ms 65ms +0%
bin-paths (cached) 69ms 69ms +0%
task-ls (cached) 278ms ⚠️ 2263ms -87%

⚠️ Warning: task-ls cached performance variance is -87%

mise-en-dev added a commit that referenced this pull request Jan 28, 2026
### 🚀 Features

- **(doctor)** add backend mismatch warnings by @jdx in
[#7847](#7847)
- **(http)** add rename_exe support for archive extraction by @jdx in
[#7874](#7874)
- **(http)** send x-mise-ci header for CI environment tracking by @jdx
in [#7875](#7875)
- **(install)** auto-install plugins from [plugins] config section by
@jdx in [#7856](#7856)
- **(registry)** add vercel by @mikecurtis in
[#7844](#7844)
- **(task)** support glob patterns in task_config.includes by @jdx in
[#7870](#7870)
- **(task)** add task templates for reusable task definitions by @jdx in
[#7873](#7873)

### 🐛 Bug Fixes

- **(backend)** change registry mismatch log from info to debug by @jdx
in [#7858](#7858)
- **(ci)** use squash merge for auto-merge-release workflow by @jdx in
[7e5e71e](7e5e71e)
- **(ci)** remove --auto flag to merge immediately when CI passes by
@jdx in
[23ed2ed](23ed2ed)
- **(github)** select platform-matching provenance file for SLSA
verification by @jdx in [#7853](#7853)
- **(go)** filter out version "1" from available versions by @jdx in
[#7871](#7871)
- **(install)** skip CurDir components when detecting archive structure
by @jdx in [#7868](#7868)
- **(pipx)** ensure Python minor version symlink exists for postinstall
hooks by @jdx in [#7869](#7869)
- **(registry)** prevent duplicate -stable suffix in Flutter download
URLs by @jdx in [#7872](#7872)
- **(task)** pass env to usage parser for env-backed arguments by @jdx
in [#7848](#7848)
- **(task)** propagate MISE_ENV to child tasks when using -E flag by
@jdx in
[06ee776](06ee776)
- **(vfox-dotnet)** use os.execute() to fix Windows installation by
@prodrigues1912 in [#7843](#7843)

### 📚 Documentation

- update cache-behavior with env_cache information by @jdx in
[#7849](#7849)

### ◀️ Revert

- remove task inheritance from parent configs in monorepos by @jdx in
[#7851](#7851)
- Revert "fix(ci): remove --auto flag to merge immediately when CI
passes" by @jdx in
[0606187](0606187)

### 📦 Registry

- add mago
([aqua:carthage-software/mago](https://github.com/carthage-software/mago))
by @scop in [#7845](#7845)

### Chore

- **(ci)** auto-merge release branch into main daily at 4am CST by @jdx
in [#7852](#7852)

### New Contributors

- @mikecurtis made their first contribution in
[#7844](#7844)
- @prodrigues1912 made their first contribution in
[#7843](#7843)
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