Task v3.54.0 Taskfile.yml 配置详解

Taskfile.yml(Schema 3)全键详解:根级配置、五类变量、任务级属性、命令对象与 includes 拆分,每项配 Ubuntu 22.04 + Task v3.54.0 实测回显,附 monorepo 生产模板。

Task任务运行器2026/10/25

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)

二、前置条件

  1. 已安装 Task v3.54.0 并验证:
task --version

实测输出:

3.54.0
  1. 建立实验目录并初始化一个最小 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
  1. 编辑器建议: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 核对):

键类型默认值作用
versionstring/number必填Schema 版本,写 '3'
outputstring/objectinterleaved输出模式:interleaved/group/prefixed
methodstringchecksum增量判定法:checksum/timestamp/none
includesmap—引入其他 Taskfile 为命名空间
varsmap—全局变量(五类写法见第六章)
envmap—注入任务环境的环境变量
dotenv[]string—加载 .env 文件,列表靠前者优先
tasksmap—任务定义(核心,见第七章)
silentboolfalse全局静默(不回显任务名与命令)
runstringalways重复调用同一任务的行为:always/once/when_changed
intervalstring100mswatch 模式轮询间隔
set[]string—全局 POSIX shell 选项(errexit/pipefail 等)
shopt[]string—全局 Bash 选项(globstar/nullglob 等)
use_gitignoreboolfalsesources/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 段可以直接核对最终生效值。

十一、参考链接