Étant très réticent à l'utilisation du Makefile, je suis récemment tombé sous le charme de Taskfile, qui permet de faire à peu près la même chose, mais avec une syntaxe plus simple.
Qu'est-ce que Taskfile ?
Taskfile est un lanceur de tâches écrit en Go, ce qui implique qu'il s'agit en fait d'un exécutable que l'on peut installer simplement en le mettant dans un dossier se trouvant dans le PATH du système par exemple.
La syntaxe de Taskfile est assez simple à prendre en main. C'est du YAML, à écrire dans un fichier Taskfile.yml. En bonus, support natif pour Windows !
Beaucoup de choses sont possibles avec Taskfile, tout comme avec Makefile :
- dépendance entre les tâches
- possibilité d'exécuter plusieurs tâches en parallèle
- éviter d'exécuter une commande si rien n'a changé (dans les fichiers composer.lock ou yarn.lock par exemple)
- meilleure lisibilité
- descriptif des tâches disponible en renseignant une simple clé
Dans mon cas, j'avais besoin de quelques raccourcis, notamment pour :
- lancer (ou arrêter) les conteneurs Docker et le serveur Symfony en une seule commande
- réinitialiser la base de données en dev avec les fixtures
- lancer les tests, avec ou sans coverage, avec les fixtures
- quand je change de branche dans un projet, n'exécuter yarn install && yarn run dev que si quelque chose a changé
Prenons un exemple : je veux lancer les conteneurs Docker, le serveur Symfony et les fixtures. Je vais lancer la commande suivante : task start fixtures, donc les tâches start (pour Docker et le binaire Symfony) et fixtures seront lancées l'une à la suite de l'autre. En ajoutant l'option --parallel, les deux tâches seront lancées en même temps.
Mon fichier Taskfile pour Symfony
Voici mon fichier Taskfile.yml (chaque tâche est décrite de telle sorte que l'on sait ce qu'elle fait) :
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/**/*
Quelques explications
Chaque tâche peut être documentée grâce à la clé desc, ce qui fait qu'en lançant la commande task -l, on obtient une liste de chaque tâche documentée ressemblant à ceci :
- 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
On peut noter que la tâche setup_tests n'apparaît pas dans cette liste, étant donné qu'elle n'est pas documentée. Tant mieux, je ne comptais pas m'en servir sans lancer les tests derrière.
Comme pour un fichier Makefile, on peut définir des dépendances entre les tâches. Par exemple, la tâche assets requiert d'abord que la tâche node_modules soit effectuée.
On notera qu'un système permet de ne pas exécuter la tâche en question si rien n'a changé depuis le dernier lancement. Par exemple pour la tâche composer, elle n'a pas besoin d'être exécutée si le composer.lock n'a pas été modifié depuis la dernière exécution.
En parlant de cela, n'oubliez pas d'ajouter l'exclusion du dossier /.task dans votre .gitignore par exemple. Ce dossier contient notamment le checksum des fichiers renseignés par le paramètre sources, qui empêche l'exécution inutile d'une tâche.
Et voilà, c'est terminé ! :) Si vous avez des questions, remarques, suggestions ... N'hésitez pas à poster un commentaire ci-dessous :)
Commentaires
Posté par Nicolas le 27/11/2020 à 11:06.
Bonjour,Ne connaissant pas Taskfile, j'ai trouvé ton article très instructif.
Au tout début de ton article tu mets que tu es très réticent à l'utilisation d'un Makefile et je suis curieux de savoir pourquoi ?
Merci d'avance.
Nicolas
Posté par jmsche le 30/11/2020 à 14:08.
Bonjour Nicolas,Je trouve simplement que la syntaxe du Makefile n'est pas des plus claires et lisibles.
Évidemment les réfractaires au YAML peuvent dire la même chose du Taskfile :)
Un gros avantage est également la prise en charge native de Windows, ce qui n'est pas le cas avec Makefile, même s'il existe plusieurs variantes pour Windows qui fonctionnent plus ou moins.
jmsche
Posté par Brian le 02/12/2020 à 21:12.
I think there is a typo in the fixtures task.symfony console h:f:l --no-interaction --quiet
should be
symfony console d:f:l --no-interaction --quiet
Thank you for making this, I'm already using it on a new Symfony project.
Posté par jmsche le 02/12/2020 à 21:17.
Hi Brian,Thanks for your comment :)
It's not a typo :) I use hautelook/alice-bundle for fixtures, not doctrine/doctrine-fixtures-bundle, hence the difference :)
Posté par Jonathan le 17/03/2021 à 14:35.
Super pratique j'avais déjà vu ça dans un projet mais j'avais pas capté l'utilité .Posté par jb dev labs le 13/06/2022 à 08:54.
Effectivement, le YAML est plus clair et plus strict que la syntaxe du Makefile et ça le rends plus interopérable. C'est un outils plus destiné aux projets dont les postes de dev sont hétérogène.