Task is awesome
I love the terminal. Like a weird amount. It’s uniquely flexible and rigid at the same time, in a way that really works for my neurodivergent brain. One of the coolest things about the terminal is the way you can script things. If there’s a task you do more than once, you can just write a script to do it for you and voila. Try doing that with a GUI! (I mean, GUIs are great too, for different reasons)
Unfortunately, bash scripting is not always the most accessible thing to learn or parse. Simple stuff is relatively straightforward, but once you get into the weeds of conditionals, loops, and functions, it can get pretty gnarly pretty quick.
Not only that, but there are often specific things you want to do in specific projects, that don’t necessarily need to be in your global environment. Particularly when there are multiple specific things with the same name that operate differently in different projects.
Enter make
. make
is the original task runner/build tool (these are slightly different things but often used interchangeably unless you’re pedantic and/or program in C a lot), and it’s still one of the best. It’s a bit weird in the syntax department, but it’s also very powerful and flexible. Kind of like a shell script, but with a bunch of extra features that make it easier to use for certain things.
So…I don’t love make
. I don’t have anything against it, I’m just kinda dumb and I like things simple. As simple as possible really. And I don’t mind using an extra tool to make things easier for myself. That’s where task
comes in.
While make
is very similar to bash scripting in its syntax, task
is configured with YAML. This makes it a lot easier to read and write if you’re a dbt-head like myself who wrangles lots of YAML. It also has a bunch of extra features that make it easier to use for certain things. It can automatically read in your environment variables, it lets you easily run things in parallel or serial, and it has a bunch of built-in features for things like logging and error handling. And where make
requires special syntax for commands that don’t produce files, task
is designed to be more intuitive and flexible and expects that you probably want to run commands that do arbitrary things.
Here’s an example Taskfile.yml (the YAML that configures task
) for this very website:
version: "3"
tasks:
dev:
aliases: ["d"]
cmds:
- astro dev
build:
aliases: ["b"]
cmds:
- astro build
- astro preview
Pretty easy right? You can run task dev
to start the development server, and task build
to build the site and preview it. I also alias task to t
, so I can also run t d
and t b
respectively. This is a really simple example, but you can imagine how this could be useful for a more complex project.
Here’s a Taskfile.yml
(the YAML that configures task
) for a dbt project that sets up a virtual environment, installs dependencies, and builds the project:
version: "3"
tasks:
venv:
cmds:
- python3 -m venv .venv
install:
cmds:
- source .venv/bin/activate && python3 -m pip install --upgrade pip
- source .venv/bin/activate && python3 -m pip install -r requirements.txt --progress-bar off
build:
cmds:
- source .venv/bin/activate && dbt deps
- source .venv/bin/activate && dbt seed
- rm -rf jaffle-data
- source .venv/bin/activate && dbt run
- source .venv/bin/activate && dbt test
setup:
cmds:
- task: venv
- task: install
- task: build
If you’re interested in checking it out for yourself, you can install task
with brew install go-task
on a Mac, or similar on whatever platform you’re using. You can also check out the official documentation for more details.