Introduction to Taskfile: A Modern Build Tool for Efficient Project Management
Taskfile, a versatile and powerful build tool, has emerged as a popular choice among developers looking for a streamlined way to automate and manage their project’s tasks. Whether you’re dealing with complex build scripts or simple automation, Taskfile offers a solution that is both intuitive and highly customizable.
What is Taskfile?
Taskfile is an open-source build tool written in Go. It provides a declarative way to define tasks in a YAML configuration file, which can be executed with the task
command. This tool is designed to be simple yet powerful, allowing you to define tasks that can run shell commands, interact with other tools, and manage dependencies between tasks.
Key Features of Taskfile
- Simplicity and Readability: Taskfile uses YAML for its configuration, making it easy to read and write. This format is both human-readable and machine-friendly, ensuring that your build scripts are easy to maintain and understand.
- Cross-Platform Compatibility: Taskfile is designed to work seamlessly on various operating systems, including Windows, macOS, and Linux. This ensures that your build processes are consistent across different environments.
- Task Dependencies: One of the standout features of Taskfile is its ability to define dependencies between tasks. This means you can specify which tasks need to run before others, ensuring that your build process follows a logical and efficient order.
- Variables and Environment Management: Taskfile allows you to define variables and manage environment settings within your tasks. This can include static values, dynamic commands, or environment variables, giving you the flexibility to configure tasks based on different contexts.
- Concurrency and Parallelism: To optimize performance, Taskfile supports running tasks concurrently where possible. This feature can significantly reduce build times by leveraging multi-core processors.
Getting Started with Taskfile
Installation
To get started with Taskfile, you need to install it on your system. You can do this by downloading the appropriate binary for your operating system from the Taskfile GitHub releases page or by using package managers
You can use Node and npm to install Task with following command
npm install -g @go-task/cli
Code language: Java (java)
You can also use, OS specific package managers
Mac OS
brew install go-task/tap/go-task
Code language: Java (java)
or
brew install go-task
Code language: Java (java)
Ubuntu
sudo snap install task --classic
Code language: Java (java)
Windows
winget install Task.Task
Code language: Java (java)
Basic Configuration
Once installed, you can create a Taskfile.yml
in the root directory of your project. Here is a simple example for spring boot project
version: '3'
tasks:
build:
cmd: mvn clean package
checkstyle:
cmd: mvn checkstyle:check
run:
cmds:
- docker-compose up -d
- mvn spring-boot:run
Code language: Java (java)
In this example:
- The build task compiles the Go project.
- The checkstyle task checks for code formatting rules
- The run task removes the build artifacts.
in above file you can observer that cmd and cmds option
Use cmd option when you want to run single command, cmds option when you want to run multiple commands.
Listing the tasks
You can list the all available tasks with below command
task --list-all
Code language: Java (java)
Running Tasks
To run a task, simply use the task
command followed by the task name:
task build
task checkstyle
task run
Code language: Java (java)
If task depends any other task, instead of repeating the commands again you can use the ‘deps’ option to specify the depending task.
version: '3'
tasks:
build:
deps:
- checkstyle
cmd: mvn clean package
checkstyle:
cmd: mvn checkstyle:check
run:
cmds:
- docker-compose up -d
- mvn spring-boot:run
Code language: YAML (yaml)
In above example, build task depends on checkstyle task, so we run
task build command, first checkstyle task will run and after that command specified in ‘cmd’ option is run.
Advanced Features
Dynamic Variables
You can define variables in your Taskfile, which can be used to make your tasks more flexible:
version: '3'
tasks:
build:
deps:
- checkstyle
cmd: mvn clean package
checkstyle:
cmd: mvn checkstyle:check
run:
cmds:
- docker-compose up -d
- mvn spring-boot:run
test:
cmd: mvn clean test
sunit:
cmd: mvn test -Dtest={{.UNIT_TEST}}
Code language: Java (java)
In above example, you can pass the UNIT_TEST variable from command line to run the single unit test.
task sunit UNIT_TEST=<unit-test-name>
Code language: Java (java)
similarly you can do for same for the spring boot integration tests also
version: '3'
tasks:
build:
deps:
- checkstyle
cmd: mvn clean package
checkstyle:
cmd: mvn checkstyle:check
run:
cmds:
- docker-compose up -d
- mvn spring-boot:run
test:
cmd: mvn clean test
sunit:
cmd: mvn test -Dtest={{.UNIT_TEST}}
it:
cmd: mvn clean verify
sit:
cmd: mvn verify -Dit.test={{.IT_TEST}}
Code language: Java (java)
You can also assign default value to dynamic variable inside Task file and override them from CLI
version: '3'
vars:
SKIP_TEST: true
tasks:
build:
deps:
- checkstyle
cmd: mvn clean package
checkstyle:
cmd: mvn checkstyle:check
run:
cmds:
- docker-compose up -d
- mvn spring-boot:run
test:
cmd: mvn clean test
sunit:
cmd: mvn test -Dtest={{.UNIT_TEST}}
it:
cmd: mvn clean verify
sit:
cmd: mvn verify -Dit.test={{.IT_TEST}}
buildskiptests:
cmd: mvn clean package -DskipTests={{.SKIP_TEST}}
Code language: Java (java)
In above example, SKIP_TEST variable is set to true, if you want to override the default value you can pass the new value from cli
task buildskiptests SKIP_TEST=false
Code language: Java (java)
Conditional Execution
Taskfile supports conditional execution of tasks based on the status of previous tasks or conditions defined within the Taskfile:
version: '3'
vars:
SKIP_TEST: true
tasks:
build:
deps:
- checkstyle
cmd: mvn clean package
checkstyle:
cmd: mvn checkstyle:check
run:
cmds:
- docker-compose up -d
- mvn spring-boot:run
preconditions:
- sh: test -f docker-compose.yml
msg: "docker-compose.yml file does not exist"
test:
cmd: mvn clean test
sunit:
cmd: mvn test -Dtest={{.UNIT_TEST}}
it:
cmd: mvn clean verify
sit:
cmd: mvn verify -Dit.test={{.IT_TEST}}
buildskiptests:
cmd: mvn clean package -DskipTests={{.SKIP_TEST}}
Code language: Java (java)
task run
Code language: Java (java)
in above example, for ‘run’ task, we are checking whether docker-compose.yml file exits in the project. If file does not exits, we see error message like below
task: docker-compose.yml file does not exist
task: precondition not met
Code language: Java (java)
Running a Taskfile from a subdirectory
f a Taskfile cannot be found in the current working directory, it will walk up the file tree until it finds one . When running Task from a subdirectory like this, it will behave as if you ran it from the directory containing the Taskfile.
You can use this functionality along with the special {{.USER_WORKING_DIR}}
variable to create some very useful reusable tasks. For example, if you have a monorepo with directories for each microservice, you can cd
into a microservice directory and run a task command to bring it up without having to create multiple tasks or Taskfiles with identical content. For example:
version: '3'
tasks:
up:
dir: '{{.USER_WORKING_DIR}}'
preconditions:
- test -f docker-compose.yml
cmds:
- docker-compose up -d
Code language: Java (java)
Running a global Taskfile
If you call Task with the --global
(alias -g
) flag, it will look for your home directory instead of your working directory. In short, Task will look for a Taskfile that matches $HOME/{T,t}askfile.{yml,yaml}
.
This is useful to have automation that you can run from anywhere in your system!
Place the Taskfile.yml file in your home directory with following content
version: '3'
tasks:
from-home:
cmds:
- pwd
from-working-directory:
dir: '{{.USER_WORKING_DIR}}'
cmds:
- pwd
Code language: Java (java)
task -g from-home // show user home directory
task -g from-working-directory // shows current working directory
Code language: Java (java)
Using Task in GitHub Actions
You can also use Task build toll in github actions with following action
- name: Install Task
uses: arduino/setup-task@v1
with:
version: 3.x
repo-token: ${{ secrets.GITHUB_TOKEN }}
Code language: Java (java)
Conclusion
Taskfile is a powerful yet simple build tool that can significantly enhance your project’s build process. Its declarative approach, coupled with features like task dependencies, variable management, and cross-platform compatibility, makes it an ideal choice for developers looking to automate and streamline their workflows. Whether you are managing a small script or a large-scale application, Taskfile provides the tools you need to maintain an efficient and organized build process.
Give Taskfile a try and see how it can transform the way you manage your project builds. For more information and advanced usage, visit the Taskfile documentation.