
1. What is Taskfile?
Taskfile describes various execution tasks using YAML, and its core is written in Go; compared to Makefile, which uses tab-separated and bash-combined syntax, Taskfile appears more modern and user-friendly (though it may turn you into a YAML engineer). Taskfile has built-in advanced features such as dynamic variables and recognition of operating system environment variables, which align more closely with modern coding practices.
Overall, if you are not very familiar with Makefile and wish to accomplish batch tasks using a tool similar to Makefile, Taskfile will be easier to get started with, offering a lower learning curve and sufficient speed.
2. Installation and Usage
Install go-task
For macOS users, the official installation method is provided via brew:
$ brew install go-task/tap/go-task
For Linux users, the official website provides installation packages for several Linux distributions, but since it only has a single binary file, there is also a quick installation script available:
# For Default Installation to ./bin with debug logging
$ sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d
# For Installation To /usr/local/bin for userwide access with debug logging
# May require sudo sh
$ sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d -b /usr/local/bin
If you already have a Go development environment locally, you can also install it directly using the go command:
$ go install github.com/go-task/task/v3/cmd/task@latest
Quick Start
After installation, you only need to create a Taskfile.yml
YAML file, and then you can run the corresponding tasks using the task
command:
version: '3'
tasks:
build:
cmds:
- echo "Executing build task"
docker:
cmds:
- echo "Packaging docker image"

If you need to set a default task to execute, just create a task named default
:
version: '3'
tasks:
default:
cmds:
- echo "This is the default task"
build:
cmds:
- echo "Executing build task"
docker:
cmds:
- echo "Packaging docker image"

3. Advanced Usage
Environment Variables
Taskfile supports referencing three types of environment variables:
-
Shell environment variables -
Environment variables defined within Taskfile -
Environment variables defined in variable files
If you need to reference a shell environment variable, simply use the $ variable_name
syntax:
version: '3'
tasks:
default:
cmds:
- echo "$ABCD"

Similarly, you can also define environment variables within the Taskfile:
version: '3'
env:
TENV2: "t2" # Global environment variable
tasks:
default:
cmds:
- echo "$TENV1"
- echo "$TENV2"
env:
TENV1: "t1" # Single task environment variable

In addition to directly referencing variables, Taskfile also supports loading environment variables from .env files similar to docker-compose; Taskfile will automatically load the .env
file in the same directory, and you can also configure specific files using the dotenv
command in Taskfile:
version: '3'
dotenv: [".env", ".testenv"]
tasks:
default:
cmds:
- echo "$ABCD"
- echo "$TESTENV"

Enhanced Variables
In addition to standard environment variables, Taskfile also includes a widely used type of enhanced variable called vars
; this variable pattern can be read using Go’s template engine (interpolation reference) and has special features that environment variables do not possess. Here is an example of vars variable:
version: '3'
# Global var variable
vars:
GLOBAL_VAR: "global var"
tasks:
testvar:
# task var variable
vars:
TASK_VAR: "task var"
cmds:
- "echo {{.GLOBAL_VAR}}"
- "echo {{.TASK_VAR}}"
In addition to the similar use of environment variables, the vars enhanced variable also supports dynamic definitions; a common scenario is that we want to get the current git commit ID every time a task is executed, at which point we can use the dynamic definition feature of vars:
version: '3'
tasks:
build:
cmds:
- go build -ldflags="-X main.Version={{.GIT_COMMIT}}" main.go
vars:
# Every time the task is executed, GIT_COMMIT will call a shell command to generate this variable
GIT_COMMIT:
sh: git log -n 1 --format=%h
The vars variable also includes some special predefined variables, such as {{.TASK}}
which always represents the current task name, and {{.CLI_ARGS}}
which can reference command line input, etc.
version: '3'
tasks:
yarn:
cmds:
- yarn {{.CLI_ARGS}}
At this point, if you execute task yarn -- install
, the value of {{.CLI_ARGS}}
will become install
, thus executing the yarn install
command.
In addition, the vars variable has other features, such as allowing for overriding and passing when referencing across tasks, which will be introduced later.
Execution Directory
Tasks defined in Taskfile are executed in the current directory by default; if you wish to execute in another directory, you can directly set the execution directory using the dir
parameter without manually writing commands like cd
:
version: '3'
tasks:
test1:
dir: /tmp # Execute in the specified directory
cmds:
- "ls"
Task Dependencies
In CI environments, we often need to define the execution order and dependencies of tasks; Taskfile provides support for task dependencies through the deps
configuration:
version: '3'
tasks:
build-jar:
cmds:
- echo "Compiling jar package..."
build-static:
cmds:
- echo "Compiling frontend UI..."
build-docker:
deps: [build-jar, build-static]
cmds:
- echo "Packaging docker image..."
Task Calls
When we define multiple tasks in Taskfile, it is likely that some tasks have certain similarities; at this point, we can define template tasks by calling tasks mutually and dynamically overriding vars variables:
version: '3'
tasks:
docker:
cmds:
#- docker build -t {{.IMAGE_NAME}} {{.BUILD_CONTEXT}}
- echo {{.IMAGE_NAME}} {{.BUILD_CONTEXT}}
build-backend:
cmds:
- task: docker # Reference another task
vars: { # Dynamically pass variables
IMAGE_NAME: "backend",
BUILD_CONTEXT: "maven/target"
}
build-frontend:
cmds:
- task: docker
vars: {
IMAGE_NAME: "frontend",
BUILD_CONTEXT: "public"
}
default: # default is called when no task name is input in the command line
cmds:
- task: build-backend
- task: build-frontend

Including Other Files
Taskfile supports including other Taskfiles using the includes
keyword, making it easier to structure Taskfiles.
It is important to note that since the included file may contain multiple tasks, you need to name the included files and reference the target tasks by name:
version: '3'
includes:
file1: ./file1.yaml # Directly reference the yaml file
dir2: ./dir2 # When referencing a directory, it defaults to referencing Taskfile.yaml in that directory

When including other Taskfiles, by default, commands will be executed in the directory of the current main Taskfile; you can also control the execution directory of tasks in the included Taskfiles using the dir
parameter:
version: '3'
includes:
dir1: ./dirtest.yaml # Directly execute in the current directory
dir2:
taskfile: ./dirtest.yaml
dir: /tmp # Execute in the specified directory

Defer Handling
Those familiar with Go should know that there is a very convenient keyword defer
in Go; this directive is used to define actions to be executed at the end of the code, such as resource cleanup. Taskfile also supports this directive, allowing us to easily perform cleanup operations during task execution:
version: '3'
tasks:
default: # default is called when no task name is input in the command line
cmds:
- wget -q https://github.com/containerd/nerdctl/releases/download/v0.19.0/nerdctl-full-0.19.0-linux-amd64.tar.gz
# Define cleanup actions
- defer: rm -f nerdctl-full-0.19.0-linux-amd64.tar.gz
- tar -zxf nerdctl-full-0.19.0-linux-amd64.tar.gz

Of course, the defer directive can also reference other tasks for cleanup:
version: '3'
tasks:
cleanup:
cmds:
- rm -f {{.FILE}}
default: # default is called when no task name is input in the command line
cmds:
- wget -q https://github.com/containerd/nerdctl/releases/download/v0.19.0/nerdctl-full-0.19.0-linux-amd64.tar.gz
# Reference other tasks for cleanup, and dynamic variables can also be passed
- defer: {task: cleanup, vars: {FILE: nerdctl-full-0.19.0-linux-amd64.tar.gz}}
- tar -zxf nerdctl-full-0.19.0-linux-amd64.tar.gz
4. Advanced Applications
Dynamic Detection
Output Detection
Sometimes, for certain tasks, we may want to implement caching, for example, if a file has already been downloaded, we do not want to repeat the download; for this requirement, Taskfile allows us to define source files and generated files, and determine whether to execute the task based on the hash values of this set of files:
version: '3'
tasks:
default:
cmds:
- wget -q https://github.com/containerd/nerdctl/releases/download/v0.19.0/nerdctl-full-0.19.0-linux-amd64.tar.gz
sources:
- testfile
generates:
- nerdctl-full-0.19.0-linux-amd64.tar.gz

From the above figure, we can see that when the task is executed for the first time, a .task
directory will be generated, which contains the hash values of the files; when the task is executed again, if the hash value does not change, the actual task will not really execute. Taskfile has two default file detection methods: checksum
and timestamp
; checksum
performs hash detection of files (default), and this mode only requires defining the sources
configuration; timestamp
performs timestamp detection of files, and this mode requires defining both sources
and generates
configurations.
version: '3'
tasks:
build:
cmds:
- go build .
sources:
- ./*.go
generates:
- app{{exeExt}}
method: checksum # Specify detection method
In addition to the two built-in detection modes, we can also define our own detection commands through the status
configuration; if the command execution result is 0, it is considered that the file is up to date and the task does not need to be executed:
version: '3'
tasks:
generate-files:
cmds:
- mkdir directory
- touch directory/file1.txt
- touch directory/file2.txt
# test existence of files
status:
- test -d directory
- test -f directory/file1.txt
- test -f directory/file2.txt
Input Detection
The above output detection is used to detect the results of the files generated by the task, and in some cases we may want to determine a condition before running the task, identifying whether the task needs to run without executing at all; at this point, we can use the preconditions
configuration directive:
version: '3'
tasks:
generate-files:
cmds:
- mkdir directory
- touch directory/file1.txt
- touch directory/file2.txt
# test existence of files
preconditions:
- test -f .env
- sh: "[ 1 = 0 ]"
msg: "One doesn't equal Zero, Halting"
Go Template Engine
In the variable section above, we have already demonstrated part of the template engine’s usage; in fact, Taskfile integrates the slim-sprig[1] library, which provides some convenient methods that can be used within the template engine:
version: '3'
tasks:
print-date:
cmds:
- echo {{now | date "2006-01-02"}}
For more details about these methods and the use of the template engine, please refer to the Go Template documentation as well as the slim-sprig[2] documentation.
Interactive Terminal
Some task commands may require an interactive terminal to execute; at this point, you can set the interactive
option for the task; when interactive
is set to true
, the task can open an interactive terminal during execution:
version: '3'
tasks:
cmds:
- vim my-file.txt
interactive: true
For more details on using Taskfile, please read its official documentation[3]; this article will not elaborate further due to space limitations.
Reference Links
slim-sprig: https://go-task.github.io/slim-sprig/
[2]slim-sprig: https://go-task.github.io/slim-sprig/
[3]Official Documentation: https://taskfile.dev/
Original: https://mritd.com/2022/04/25/taskfile-a-better-build-tool-than-makefile/
This article is reprinted from: 「Cloud Native Laboratory」; original: https://url.hi-linux.com/Wfp51, copyright belongs to the original author. Welcome contributions, submission email: [email protected].
Recently, we have established a technical exchange WeChat group. Many industry experts have already joined the group; interested students can join us for technical discussions by replying 「Join Group」 directly in the WeChat public account 「Wonderful Linux World」.
You might also like
Click the image below to read
Analysis of Kafka Principles and Partition Allocation StrategyClick the image above, ‘Meituan|Ele.me’ delivery red envelopes are free every day
For more interesting internet news, follow the ‘Wonderful Internet’ video account to stay updated!