Jonathan Scheiber

Ma configuration Taskfile pour Symfony

Temps de lecture : 5 minutes 6 commentaires
Ma configuration Taskfile pour Symfony

É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.

Ajouter un commentaire