Task v3.54.0 Taskfile.yml 配置详解
Taskfile.yml(Schema 3)全键详解:根级配置、五类变量、任务级属性、命令对象与 includes 拆分,每项配 Ubuntu 22.04 + Task v3.54.0 实测回显,附 monorepo 生产模板。
Task v3.54.0 Taskfile.yml 配置详解
目标:系统讲清 Task(go-task/task)v3.54.0 的任务定义文件
Taskfile.yml全部配置键:根级配置、五类变量体系、任务级属性、命令对象与 includes 拆分组织,每类配置均给出可独立执行的实测示例与真实回显。本文命令与回显已在 Ubuntu 22.04 + Task v3.54.0 实测通过(安装见 《Ubuntu 22.04 安装 Task v3.54.0 指南》);选型背景见 《Task v3.54.0 介绍与选型指南》。
一、环境信息
- 操作系统:Ubuntu 22.04 LTS(x86_64)
- Task 版本:v3.54.0(
task --version实测输出3.54.0) - Taskfile Schema 版本:3(Taskfile.yml 顶部
version: '3') - 实验项目目录:
/opt/demo/(下文所有示例在此目录独立执行,含Taskfile.yml、子目录backend/Taskfile.yml、.env、src/) - 官方 Schema 参考:https://taskfile.dev/reference/schema (本文键名与默认值均与该页逐项核对,查询日期 2026-10-25)
二、前置条件
- 已安装 Task v3.54.0 并验证:
task --version
实测输出:
3.54.0
- 建立实验目录并初始化一个最小 Taskfile(后续章节的示例都可按需并入该文件独立运行):
mkdir -p /opt/demo/backend /opt/demo/src && cd /opt/demo
printf 'app content v1\n' > src/app.txt
printf 'DATABASE_URL=postgres://admin:q1w2e3r4@localhost:5432/demo\n' > .env
task --init
实测输出:
Taskfile created: Taskfile.yml
- 编辑器建议:Taskfile.yml 首行注释挂官方 JSON Schema,获得键名补全与校验:
# yaml-language-server: $schema=https://taskfile.dev/schema.json
task --init 生成的模板自带该注释行(实测文件首行即为此注释)。
三、Taskfile 的查看与校验方式
配置改完不跑一遍怎么确认生效?Task 提供四个不产生副作用的检查手段:
task --dry build
干跑:编译并打印将要执行的命令序列但不执行。实测输出:
task: [build] mkdir -p dist
task: [build] cp src/app.txt dist/app.txt
task: [build] echo "built a1b2c3d"
task --summary build
打印任务编译后的完整摘要:desc、变量求值结果、生效 env、命令列表。实测输出(节选,实测首尾):
task: build
编译产物(sources/generates 增量演示)
vars:
APP_NAME: "demo-app"
GREETING: "Hello"
TARGET: "World"
COMMIT_HASH: sh: echo a1b2c3d
BUILD_VERSION: "Hello"
CONFIG:
database: postgres
cache: redis
env:
APP_ENV: "production"
DATABASE_URL: "postgres://admin:q1w2e3r4@localhost:5432/demo"
commands:
- mkdir -p dist
- cp src/app.txt dist/app.txt
- echo "built "
task --list --json | head -c 600
机器可读清单(含每个任务在 Taskfile 中的行列位置与增量状态),适合 CI 巡检。实测输出(节选):
{
"tasks": [
{
"name": "build",
"task": "build",
"desc": "编译产物(sources/generates 增量演示)",
"aliases": [],
"up_to_date": true,
"location": {
"line": 38,
"column": 3,
"taskfile": "/opt/demo/Taskfile.yml"
}
},
task --experiments
查看实验特性开关。实测输出(v3.54.0 当前全部实验):
* GENTLE_FORCE: off
* ENV_PRECEDENCE: off
四、根级配置键总览
Taskfile.yml 顶层可用的全部键(Schema 3,来源:官方 Schema 参考,2026-10-25 核对):
| 键 | 类型 | 默认值 | 作用 |
|---|---|---|---|
version | string/number | 必填 | Schema 版本,写 '3' |
output | string/object | interleaved | 输出模式:interleaved/group/prefixed |
method | string | checksum | 增量判定法:checksum/timestamp/none |
includes | map | — | 引入其他 Taskfile 为命名空间 |
vars | map | — | 全局变量(五类写法见第六章) |
env | map | — | 注入任务环境的环境变量 |
dotenv | []string | — | 加载 .env 文件,列表靠前者优先 |
tasks | map | — | 任务定义(核心,见第七章) |
silent | bool | false | 全局静默(不回显任务名与命令) |
run | string | always | 重复调用同一任务的行为:always/once/when_changed |
interval | string | 100ms | watch 模式轮询间隔 |
set | []string | — | 全局 POSIX shell 选项(errexit/pipefail 等) |
shopt | []string | — | 全局 Bash 选项(globstar/nullglob 等) |
use_gitignore | bool | false | sources/generates 解析时是否应用 .gitignore |
💡 说明:一张配置文件的骨架通常是「version 打头 → 全局行为(output/method/run)→ 变量(vars/env/dotenv)→ includes → tasks」,与 YAML 阅读顺序一致。
tasks是唯一必填目标,其余键按需出现。
五、根级配置详解
5.1 version:Schema 版本声明
version: '3'
- 必填;接受
'3'、3或完整 semver 字符串。指 Taskfile 语法的 Schema 版本而非 Task 软件版本:v3.x 的 Task 读取 Schema 3,写错会直接解析报错。生产建议加引号写成'3',避免被 YAML 解析成数字。
5.2 output:并行输出的三种整理方式
多任务并行(deps、--parallel)时输出会交错,output 决定整理方式:
| 模式 | 行为 | 适用 |
|---|---|---|
interleaved(默认) | 实时逐行输出,多任务交错 | 本地交互 |
group | 每个任务的输出聚成一组,结束后一次性打印 | CI 折叠日志 |
prefixed | 每行前加 [任务名] 前缀 | 并行时区分来源 |
实测三种模式(同一批任务):
task --output group group-output
实测输出:
task: [group-output] echo one && sleep 0.2
one
two
task: [group-output] echo two
task --output prefixed --parallel hello cli-args
实测输出:
task: [cli-args] echo "args are "
task: [hello] echo 'Hello World! (demo-app v3)'
[cli-args] args are
[hello] Hello World! (demo-app v3)
group 还支持对象形式自定义组首尾模板(如 begin: "::group::{{.TASK}}"),与 GitHub Actions 日志折叠语法配合;error_only: true 可只在失败时展开组。
5.3 method:增量判定的默认策略
| 取值 | 判定原理 | 取舍 |
|---|---|---|
checksum(默认) | 对 sources 文件内容做哈希,与 .task/ 下记录比对 | 内容不变不重跑;重命名目录会失效 |
timestamp | 比对 sources 与 generates 的 mtime | 纯 Make 语义,git clone 后 mtime 变化可能误判 |
none | 永不判新,每次都跑 | 部署/清理类任务 |
实测:同一任务连续两次执行,第二次被判定跳过(checksum 默认法):
task build
第一次实测输出:
task: [build] mkdir -p dist
task: [build] cp src/app.txt dist/app.txt
task: [build] echo "built a1b2c3d"
built a1b2c3d
task build
第二次实测输出:
task: Task "build" is up to date
改用 timestamp 法的任务(method: timestamp)实测同样两段式:第一次执行、第二次 task: Task "timestamp-build" is up to date。.task/ 临时目录存放哈希状态,删除它即可强制全量重跑。
5.4 silent / set / shopt:全局静默与 shell 语义
silent: true # 不回显 "task: [任务名] 命令",只看命令自身输出
set: [errexit, pipefail] # 每条命令的 shell 打开 -e -o pipefail
shopt: [globstar] # Bash 扩展 glob:** 匹配多层目录
实测静默(任务 fail-silent 声明 silent: true):
task fail-silent
实测输出:
你只能看到这行,没有任务名回显
💡 说明:
set/shopt可用的选项与 POSIX/bash 一致(set支持 errexit/nounset/xtrace/pipefail 等,shopt支持 globstar/nullglob/expand_aliases),也可下放到单个命令对象上精确控制(见 7.7)。默认不开启 errexit——shell 默认语义下命令逐条执行、失败即停当前任务但前面成功的结果保留,需要严格模式时显式声明。
5.5 run / interval:重复调用与 watch 节奏
run: once # 同一次运行中重复调用的任务只执行一次
interval: 1s # watch 轮询间隔(默认 100ms,格式 ^[0-9]+(m|s|ms)$)
run: once 适合「依赖图里多个任务都依赖 setup,但 setup 只该跑一遍」的场景;when_changed 则按传入变量是否变化决定重跑。watch 模式(task -w <任务>)按 interval 轮询 sources,实测监听构建任务时修改源文件后自动重跑:
task -w build
实测输出(修改 src/app.txt 触发一次重跑):
task: Started watching for tasks: build
task: Task "build" is up to date
task: task "build" finished running
task: [build] mkdir -p dist
task: [build] cp src/app.txt dist/app.txt
task: [build] echo "built a1b2c3d"
built a1b2c3d
task: task "build" finished running
六、变量体系详解
6.1 五类变量写法
vars:
APP_NAME: demo-app # ① 静态值(字符串/数字/布尔/数组)
GREETING: Hello
COMMIT_HASH: # ② 动态变量:执行 shell 取值
sh: echo a1b2c3d
BUILD_VERSION: # ③ ref:引用已定义变量的"活引用"
ref: .GREETING
CONFIG: # ④ map:结构化映射,可嵌套取 {{.CONFIG.database}}
map:
database: postgres
cache: redis
API_KEY: # ⑤ secret:日志打码,运行时仍传真实值
sh: echo sk-live-1234567890abcdef
secret: true
💡 技术拓展:配置文件的「变量注入」不止 Taskfile 内部这五类,外部通道还有三种——
通道 写法 优先级 命令行 task hello TARGET=Quzuo最高(覆盖文件内同名) 环境变量注入 env:键任务运行环境 dotenv 文件 dotenv: ['.env']按列表顺序,靠前优先 排查变量实际值用
task --summary <任务>,变量求值结果一览无余。
实测(任务把变量逐个打印):
task vars-demo
实测输出:
task: [vars-demo] echo 'TASK=vars-demo TASKFILE_DIR=/opt/demo'
TASK=vars-demo TASKFILE_DIR=/opt/demo
task: [vars-demo] echo 'ROOT_DIR=/opt/demo USER_WORKING_DIR=/opt/demo'
ROOT_DIR=/opt/demo USER_WORKING_DIR=/opt/demo
task: [vars-demo] echo 'ITEM=1'
ITEM=1
task: [vars-demo] echo 'postgres + redis + Hello'
postgres + redis + Hello
最后一行同时验证了 map 取值(CONFIG.database/CONFIG.cache)与 ref 引用(BUILD_VERSION 取到 Hello)。
6.2 特殊变量(Task 内建)
| 变量 | 含义 | 实测值 |
|---|---|---|
{{.TASK}} | 当前任务名 | vars-demo |
{{.TASKFILE_DIR}} | 当前 Taskfile 所在目录 | /opt/demo |
{{.ROOT_DIR}} | 根 Taskfile 所在目录 | /opt/demo |
{{.USER_WORKING_DIR}} | 调用 task 命令时所在目录 | /opt/demo |
{{.CLI_ARGS}} | -- 之后透传的参数 | --foo bar |
{{.ITEM}} | for 循环当前项 | alice 等 |
实测 CLI_ARGS 透传:
task cli-args -- --foo bar
实测输出:
task: [cli-args] echo "args are --foo bar"
args are --foo bar
6.3 secret:日志打码但不影响运行
task secret-demo
实测输出(注意两行差异:回显行已打码,程序真实输出未打码):
task: [secret-demo] echo "key is *****"
key is sk-live-1234567890abcdef
secret: true 只遮蔽 Task 的命令回显日志,传给命令本身的值是真实的;适用于防止密码出现在 CI 日志里,但不能替代凭据管理(真实密钥建议仍由环境变量/vault 注入)。
6.4 env 与 dotenv
env:
APP_ENV: production
dotenv: ['.env']
env注入每个任务进程的环境变量,写法与 vars 相同(也支持sh:动态取值)。dotenv加载 .env 文件;同一变量在多个文件出现时列表靠前的文件优先(.env.local放.env前面即可实现本地覆盖)。实测--summary的 env 段中可见 dotenv 注入的DATABASE_URL(见第三章回显)。
七、任务级配置详解
7.1 任务的三种写法与 cmds/cmd
tasks:
hello: echo "hi" # ① 字符串速记
build: # ② 命令数组
- go mod tidy
- go build ./...
test: # ③ cmd 单命令对象
cmd: go test ./...
数组内每一项可以是纯字符串命令,也可以是对象(见 7.7);cmds(多条顺序执行)与 cmd(单条)二选一。
7.2 deps:并行依赖与 task 引用
tasks:
deploy:
deps: [build, test] # build 与 test 并行执行,全部成功后跑 cmds
cmds:
- ./deploy.sh
call-with-vars:
cmds:
- task: build # 命令位置引用其他任务
vars: {ENVIRONMENT: production}
deps 里的任务默认并行,配合根级 -C/--concurrency 可限并发;silent: true 可让依赖执行不回显。
7.3 desc / summary / aliases:清单与别名
desc:一行描述,出现在task --list中;无 desc 的任务只显示在--list-all。summary:长说明,由task --summary <任务>展示。aliases: [compile, make]:任务别名,task compile与task build等价。
7.4 sources / generates:增量构建
tasks:
build:
sources:
- src/*.txt
- exclude: src/*_test.txt # glob 排除项
generates:
- dist/app.txt
cmds:
- mkdir -p dist
- cp src/app.txt dist/app.txt
判定逻辑:sources 任一文件内容(checksum 法)或时间戳(timestamp 法)相对 generates 变化 → 重跑;否则输出 Task "build" is up to date(实测见 5.3)。修改源文件后立刻恢复重跑:
printf 'x\n' >> src/app.txt && task build
实测输出:
task: [build] mkdir -p dist
task: [build] cp src/app.txt dist/app.txt
task: [build] echo "built a1b2c3d"
built a1b2c3d
generates 指向的产物文件会被记录用于比对与清理;任务级 use_gitignore: true 可在解析 glob 时排除 .gitignore 命中的文件。
7.5 status / preconditions / if:三道闸门
| 属性 | 语义 | 失败后果 |
|---|---|---|
status | 命令成功(exit 0)= 已是最新 → 跳过任务 | 不执行,静默跳过 |
preconditions | 前置条件不满足 → 拒绝执行 | 报错,退出码 201 |
if | 为假 → 本次不执行 | 静默跳过(不算失败) |
tasks:
install-deps:
status:
- test -f vendor/.installed # 标记文件存在就不再装依赖
cmds:
- echo "installing deps" && mkdir -p vendor && touch vendor/.installed
precond-demo:
preconditions:
- sh: test -f required.txt
msg: 'required.txt 不存在,先运行 task setup'
cmds: [echo "preconditions passed"]
实测 status 两连跑(第一次装依赖、第二次跳过):
task: [status-demo] echo "installing deps" && mkdir -p vendor && touch vendor/.installed
installing deps
task: Task "status-demo" is up to date
实测 preconditions 缺文件:
task precond-demo; echo exit=$?
实测输出:
task: required.txt 不存在,先运行 task setup
task: Failed to run task "precond-demo": task: precondition not met
exit=201
💡 说明:status 与 sources 的选择——status 适合「检查副作用是否已发生」(如依赖目录已存在),sources/generates 适合「输入变了产物要重建」;两者可同任务并用,任一判定「已是最新」即跳过。
7.6 requires:必需变量与枚举校验
tasks:
requires-demo:
requires:
vars:
- name: ENVIRONMENT
enum: [development, production]
cmds:
- echo "deploy to {{.ENVIRONMENT}}"
三种实测:缺变量(退出码 206)、枚举外取值(207)、合法取值:
task requires-demo; echo exit=$?
task: Task "requires-demo" cancelled because it is missing required variables: ENVIRONMENT (allowed values: [development production])
exit=206
task requires-demo ENVIRONMENT=staging; echo exit=$?
task: Task "requires-demo" cancelled because it is missing required variables:
- ENVIRONMENT has an invalid value : 'staging' (allowed values : [development production])
exit=207
task requires-demo ENVIRONMENT=production
task: [requires-demo] echo "deploy to production"
deploy to production
枚举校验把「环境名打错」拦在执行前,比在 shell 里手写 case 校验可靠;配合 CLI --interactive 可对缺失变量交互式补齐。
7.7 命令对象:silent / ignore_error / defer / task 引用 / for 循环
cmds 数组项的完整对象形态:
cmds:
- cmd: make lint
silent: true # 该命令不回显
ignore_error: true # 失败不中断任务
platforms: [linux, darwin] # 仅在指定平台执行
timeout: 5m # 单命令超时
set: [errexit] # 该命令专属 shell 选项
- task: cleanup # 引用其他任务(可带 vars)
vars: {MODE: full}
- defer: echo "cleanup ran" # 注册清理:任务结束(无论成败)必执行
- for: [alice, bob] # for 循环
cmd: echo "Hello {{.ITEM}}"
实测 ignore_error(false 失败但任务继续、整体退出 0):
task ig; echo exit=$?
task: [ig] false
task: [ig] echo 'still running'
still running
exit=0
实测 defer(命令 exit 1 失败后清理仍执行,任务整体失败退出 201):
task defer-demo; echo exit=$?
task: [defer-demo] exit 1
task: [defer-demo] echo "cleanup ran"
cleanup ran
task: Failed to run task "defer-demo": exit status 1
exit=201
实测 for 循环与矩阵组合:
task loop-demo
task: [loop-demo] echo "Hello alice"
task: [loop-demo] echo "Hello bob"
Hello alice
Hello bob
task: [loop-demo] echo "matrix linux/amd64"
task: [loop-demo] echo "matrix darwin/amd64"
matrix linux/amd64
matrix darwin/amd64
for 的四种遍历目标:字面列表(上例)、for: sources(遍历增量输入文件)、变量(var: ITEMS + split: ',' + as: CURRENT)、矩阵(matrix: 多维笛卡尔积,{{.ITEM.OS}} 取维度)。deps 里同样支持 for(批量带变量调用子任务)。
7.8 prompt:危险操作二次确认
tasks:
prompt-demo:
prompt: '确定要删除构建产物吗?'
cmds: [echo "cleaned"]
非终端环境(CI)执行会被自动拒绝,退出码 205:
task prompt-demo; echo exit=$?
task: Failed to run task "prompt-demo": task: Task "prompt-demo" cancelled because it has a prompt and the environment is not a terminal. Use --yes (-y) to run anyway.
exit=205
确认放行用 -y:
task prompt-demo -y
task: [prompt-demo] echo "cleaned"
确定要删除构建产物吗? [assuming yes]
cleaned
prompt 还接受数组(多连问),是 rm -rf、drop table 类任务的标配保险。
7.9 watch / platforms / dir / vars(任务级)
| 属性 | 作用 | 说明 |
|---|---|---|
watch: true | 任务默认以 watch 模式运行 | task dev 等价 task -w dev |
platforms: [linux, darwin] | 平台过滤 | 不匹配的平台跳过该任务 |
dir: ./backend | 任务执行目录 | 影响所有相对路径 |
vars: | 任务级变量 | 就近覆盖全局同名变量 |
八、includes:Taskfile 拆分与命名空间
大型项目把任务拆到子目录,根 Taskfile 用 includes 聚合:
includes:
backend:
taskfile: ./backend # 目录(自动找其中 Taskfile.yml)或具体文件
dir: ./backend # 该命名空间下任务的默认执行目录
vars:
SERVICE_NAME: backend # 传给子 Taskfile 的变量
aliases: [be] # 命名空间别名
# optional: true # 文件不存在不报错
# flatten: true # 任务不带命名空间前缀直接合入
# internal: true # 从 --list 与命令行隐藏,仅供内部引用
# excludes: [debug:*] # 排除子 Taskfile 中的部分任务
optional-inc:
taskfile: ./not-exist.yml
optional: true
实测(backend:build 在子目录里执行且拿到传入变量):
task backend:build
task: [backend:build] echo "building backend in $(pwd)"
building backend in /opt/demo/backend
命名空间与执行目录同时生效:任务名前缀 backend:,$(pwd) 落在 ./backend。实测 flatten(子任务不带前缀合入主清单):
task --list
task: Available tasks for this project:
* setup: 公共初始化
💡 说明:
optional: true的容错在本文所有示例运行中均验证——not-exist.yml并不存在,Task 未报错、其余任务照常执行。远程 Taskfile(taskfile:填 https URL)也走 includes 声明,必须配checksum:锁定完整性,生产慎用(引入供应链风险面)。
九、生产配置模板(Go 服务 + 前端 monorepo 场景)
适用场景:8GB+ 内存开发机与 CI 环境、Go 后端 + Node 前端的 monorepo 仓库。以下模板综合了前述全部机制,可直接落地改参数:
# yaml-language-server: $schema=https://taskfile.dev/schema.json
version: '3'
output: prefixed # 并行时区分来源,CI 日志可读
method: checksum # 内容级增量,git 操作不误判
set: [errexit, pipefail] # 严格 shell 语义
dotenv: ['.env.local', '.env'] # 本地配置优先于默认配置
vars:
GOFLAGS: '-trimpath'
LDFLAGS: '-s -w'
includes:
backend:
taskfile: ./backend
dir: ./backend
frontend:
taskfile: ./frontend
dir: ./frontend
tasks:
default:
desc: 显示任务清单
silent: true
cmds: [task --list]
build:
desc: 编译全部(后端并行、前端串行)
deps: [backend:build]
cmds: [task frontend:build]
test:
desc: 全量测试
deps: [backend:test, frontend:test]
lint:
desc: 代码检查(失败不阻塞后续)
cmds:
- cmd: golangci-lint run ./...
ignore_error: true
- cmd: npm --prefix frontend run lint
ci:
desc: CI 一键入口
cmds:
- task: lint
- task: test
- task: build
clean:
desc: 清理产物(危险操作加确认)
prompt: '确认删除全部构建产物?'
cmds:
- rm -rf backend/bin frontend/dist .task
dev:
desc: 监听源码变化自动重编译
dir: ./backend
watch: true
sources: ['**/*.go']
generates: [bin/server]
cmds:
- go build -trimpath -ldflags '{{.LDFLAGS}}' -o bin/server ./cmd/server
模板要点:危险任务挂 prompt;deps 承担并行;.task/ 与产物目录进 .gitignore;任务粒度保持「一条 desc 一件事」,复杂逻辑下沉到脚本文件由 cmds 调用。
十、常见问题(FAQ)
Q1:为什么改了 Taskfile 再跑还是提示 up to date?
增量状态记录在项目根的 .task/ 目录(checksum/时间戳)。sources 没变就判定最新——Taskfile 本身的修改不会触发重跑。验证与强制手段:task --dry <任务> 看将要执行什么;task --force <任务> 强制执行;删除 .task/ 全量重置。
Q2:{{.VAR}} 渲染出来是空?
逐层排查:变量作用域(任务级 vars: 覆盖根级;includes 传入的变量只在对应命名空间可见);动态 sh: 变量在 Taskfile 加载时执行一次,依赖命令不存在会得到空值;ref: 引用要写 .VAR 带点前缀。最终手段:task --summary <任务> 看每个变量的求值结果。
Q3:命令里有 {{...}} 被误渲染了?
Taskfile 中所有 {{ }} 都会被 Go template 引擎处理,字面量需转义({{{{}})。另一种做法是把含模板语法的脚本放进独立文件,Task 只负责调用。
Q4:watch 模式对大仓库 CPU 占用高?
interval 默认 100ms 轮询,sources glob 范围越大扫描越重。收窄 glob(只盯源码目录)、调大 interval(如 500ms)可显著降低占用。
Q5:CI 里 prompt 任务直接失败?
设计如此:非终端环境 prompt 自动拒绝(退出码 205),防止无人值守误触发危险操作。自动化流水线中显式传 -y,或给 CI 单独定义无 prompt 的任务。
Q6:.env 与 env: 同名变量谁生效?
env: 键(Taskfile 内声明)优先于 dotenv 文件;dotenv 列表内靠前文件优先。用 task --summary 的 env 段可以直接核对最终生效值。
十一、参考链接
- Taskfile Schema 官方参考(本文键名/默认值依据):https://taskfile.dev/reference/schema
- 官方 JSON Schema:https://taskfile.dev/schema.json
- Usage 指南(变量/任务/包含机制):https://taskfile.dev/usage
- 官方 CLI 参数参考:https://taskfile.dev/reference/cli
- 本专栏前置篇:《Task v3.54.0 介绍与选型指南》、《Ubuntu 22.04 安装 Task v3.54.0 指南》