一、Taskfile 是什么❡
Taskfile 通过 yaml 来描述各种执行任务, 其核心采用 go 编写; 相较于 Makefile 的 tab 分割和 bash 结合语法 Taskfile 显得更加现代化和易于使用(虽然会变成 yaml 工程师). Taskfile 内置了动态变量、操作系统等环境变量识别等高级功能都更贴合现代化的 Coding 方式.
总体来说如果你是一个对 Makefile 不太熟悉的人, 又期望通过类似 Makefile 的工具完成一些批量任务, 那么相对于 Makefile 来说 Taskfile 会更加便于入门, 学习曲线更低且速度也足够快.
二、安装及使用❡
2.1、安装 go-task❡
对于 mac 用户来说官方提供了 brew 安装方式:
1
|
SH
|
对于 Linux 用户, 官方提供了部分 Linux 发行版的安装包, 但由于其只有一个二进制文件, 所以官方也提供了快速安装脚本:
1 |
SH
|
如果本地已经有了 Go 语言开发环境也可以直接通过 go 命令安装:
1
|
SH
|
2.2、快速开始❡
安装完成后, 只需要编写一个
Taskfile.yml
的 yaml 文件, 然后就可以通过 task
命令运行相应的任务:
1 |
YAML
|
如果需要设置默认执行任务, 只需要创建一个名字为
default
的任务即可:
1 |
YAML
|
三、进阶使用❡
3.1、环境变量❡
Taskfile 支持引用三种环境变量:
- Shell 环境变量
- Taskfile 内定义的环境变量
- 变量文件内定义的环境变量
如果需要引用 Shell 内的环境变量只需要使用
$变量名
方式直接引用即可:
1 |
YAML
|
同样在 Taskfile 内也可以定义环境变量:
1 |
YAML
|
除了这种直接引用变量的方式, Taskfile 也支持类似 docker-compose 一样读取 env 文件来加载环境变量; Taskfile 会默认加载同级目录下的
.env
文件, 也可以在 Taskfile 内通过 dotenv
命令来配置特定文件:
1 |
YAML
|
3.2、增强变量❡
除了标准的环境变量以外, 在 Taskfile 中还内置了一种使用更加广泛的增强变量
vars
; 该变量模式可以通过 go 的模版引擎进行读取(插值引用), 且具有环境变量不具备的特殊特性. 以下为 vars 变量的示例:
1 |
YAML
|
除了上面与环境变量类似的使用以外, vars 增强变量还支持动态定义; 常见的场景, 比如我们想每次 task 执行时都获取当前的 git commit id, 此时可以使用 vars 的动态定义特性:
1 |
YAML
|
vars 变量还内置了一些特殊的预定义变量, 例如
{{.TASK}}
变量永远表示当前的任务名称、{{.CLI_ARGS}}
可以引用命令行输入等.
1 |
YAML
|
此时如果执行
task yarn -- install
, 那么 {{.CLI_ARGS}}
值将会变成 install
从而执行 yarn install
命令.除此之外, vars 变量还具备一些其他特性, 比如跨任务引用时可进行覆盖传递等, 这些特性将会在后面介绍.
3.3、执行目录❡
Taskfile 内定义的 task 默认在当前目录下执行, 如果期望在其他目录执行, 无需手动编写
cd
等命令, 可以直接通过配置 dir
参数来设置执行目录:
1 |
YAML
|
3.4、任务依赖❡
在 CI 等环境的使用中, 我们常常需要定义任务的执行顺序和依赖关系; Taskfile 中通过
deps
配置来提供任务依赖关系的支持:
1 |
YAML
|
3.5、任务调用❡
当我们在 Taskfile 中定义了多个任务时, 很可能一些任务具有一定的相似性, 此时我们可以通过任务互相调用和 vars 变量动态覆盖的方式来定义模版 Task:
1 |
YAML
|
3.6、引入其他文件❡
Taskfile 支持通过
includes
关键字来引入其他 Taskfile, 从而方便 Taskfile 的结构化处理.需要注意的是, 由于引入的文件中可能会包含多特 task, 所以在使用时需要对引入的文件进行命名, 且通过命名引用目标 task:
1 |
YAML
|
在引入其他 Taskfile 时, 默认情况下会在当前主 Taskfile 目录下执行命令, 我们同样可以通过
dir
参数来控制引入的 Taskfile 内的 task 在特定目录下执行:
1 |
YAML
|
3.7、defer 处理❡
熟悉 go 语言的同学应该知道, go 里面有个很方便的关键字
defer
; 该指令用于定义在最终代码收尾时要执行的动作, 常见的比如资源清理等. Taskfile 中同样支持了该指令, 可以方便我们在任务执行期间完成一些清理操作:
1 |
YAML
|
当然, defer 指令除了直接写命令以外, 还可以引用其他 task 完成清理:
1 |
YAML
|
四、高级应用❡
4.1、动态检测❡
4.1.1、输出检测❡
在某些时候, 一些任务我们可能期望进行缓存处理, 比如说已经下载好了文件就不要重复运行下载; 针对于这种需求, Taskfile 允许我们定义源文件和生成的文件, 通过这组文件的 hash 值来确定是否需要执行该任务:
1 |
YAML
|
从上图中可以看到, 当首次执行任务时会生成
.task
目录, 该目录包含文件的 hash 值; 当重复执行任务时, 如果 hash 值不改变则真实任务不会真正执行. Taskfile 默认有两种文件检测的方式: checksum
、timestamp
, checksum
执行文件的 hash 检测(默认), 该模式只需要定义 sources
配置; timestamp
执行文件的时间戳检测, 该模式需要同时定义 sources
和 generates
配置.
1 |
YAML
|
除了内置的两种检测模式外, 我们还可以通过
status
配置来定义自己的检测命令, 如果命令执行结果为 0, 则认为文件是最新的, 不需要执行任务:
1 |
YAML
|
4.1.2、输入检测❡
上面的输出检测用于检测任务生成的文件结果等, 在某些情况下我们可能期望在运行任务之前来判断某个条件, 在完全不执行的情况下确定任务是否需要运行; 此时我们可以使用
preconditions
配置指令:
1 |
YAML
|
4.2、Go 模版引擎❡
在上面变量环节中已经展示了一部分模版引擎的使用, 实际上 Taskfile 内集成了 slim-sprig 库, 该库中提供了一些比较便利的方法, 这些方法都可以在模版引擎内使用:
1 |
YAML
|
关于这些方法和模版引擎的使用具体请参考 Go Template 相关文档以及 slim-sprig 文档.
4.3、交互式终端❡
有些任务命令可能需要交互式终端来执行, 此时可以为 task 设置
interactive
选项; 当 interactive
设置为 true
时, task 在运行时可以打开交互式终端:
1 |
YAML
|
更多关于 Taskfile 的细节使用请阅读其官方文档, 本文限于篇幅不在过多阐述.