Being reluctant to use Makefiles, I recently fell in love with Taskfile, which allows to do pretty much the same thing, but with a simpler syntax.
What is Taskfile?
Taskfile is a task launcher written in Go, which implies that it is in fact an executable that can be installed simply by putting it in a folder located in the system's PATH for example.
The syntax of Taskfile is quite easy to learn. It's YAML, to be written to a Taskfile.yml file. As a bonus, native support for Windows!
A lot of things are possible with Taskfile, just like with Makefile:
- dependency between tasks
- possibility of performing several tasks in parallel
- avoid executing a command if nothing has changed (in composer.lock or yarn.lock files for example)
- better readability
- description of the tasks available by entering a simple key
Let's take an example: I want to run Docker containers, Symfony server and fixtures. I'll run the following command: task start fixtures, so the start task (for Docker and the Symfony binary) and fixtures task will be run one after the other. By adding the --parallel option, both tasks will be started at the same time.
My Taskfile for Symfony
Here is my Taskfile.yml file (each task is described so that we know what it is doing):
version: '3' tasks: fixtures: desc: Generate fixtures for dev environment cmds: - symfony console d:d:d --force --if-exists --quiet - symfony console d:d:c --quiet - symfony console d:s:u --force --quiet - symfony console d:m:sync-metadata-storage --quiet - symfony console d:m:v --add --all --quiet - symfony console h:f:l --no-interaction --quiet composer: desc: Install PHP vendors cmds: - composer install sources: - composer.lock generates: - vendor/**/* start: desc: Start Docker containers & Symfony server cmds: - docker-compose up -d - symfony serve -d stop: desc: Stop Docker containers & Symfony server cmds: - docker-compose stop - symfony server:stop test: desc: Run tests cmds: - task: setup_tests - symfony run bin/phpunit coverage: desc: Run tests with coverage cmds: - task: setup_tests - symfony php -dpcov.enabled=1 bin/phpunit --coverage-html=public/coverage setup_tests: cmds: - symfony console d:d:d --force --if-exists --quiet --env=test - symfony console d:d:c --quiet --env=test - symfony console d:s:u --force --quiet --env=test - symfony console h:f:l --no-interaction --quiet --env=test ci: desc: Check code style, static analysis... cmds: - symfony composer ci cs-fix: desc: Fix code style cmds: - symfony composer cs:fix node_modules: desc: Update frontend vendors cmds: - yarn install sources: - yarn.lock generates: - node_modules/**/* assets: desc: Build frontend assets cmds: - task: node_modules - yarn run dev sources: - assets/**/* generates: - public/build/**/*
Each task can be documented using the desc key, so that by running the task -l command, we get a list of each documented task looking like this:
- assets: Build frontend assets
- ci: Check code style, static analysis...
- composer: Install PHP vendors
- coverage: Run tests with coverage
- cs-fix: Fix code style
- fixtures: Generate fixtures for dev environment
- node_modules: Update frontend vendors
- start: Start Docker containers & Symfony server
- stop: Stop Docker containers & Symfony server
- test: Run tests
Note that the setup_tests task does not appear in this list, as it is not documented. So much the better, I did not intend to use it without launching the tests after.
As for a Makefile, you can define dependencies between tasks. For example, the assets task first requires the node_modules task to be performed.
Note that a system makes it possible not to execute the task in question if nothing has changed since the last launch. For example for the composer task, it does not need to be executed if the composer.lock file has not been modified since the last execution.
Speaking of which, don't forget to add the exclusion of the /.task folder in eg. your .gitignore file. This folder notably contains the checksum of the files entered by the sources parameter, which prevents the unnecessary execution of a task.
Et voilà! :) If you have any questions, comments, suggestions... Feel free to post a comment below :)