Task une alternative à Make
Mise à jour :
Task est un outil puissant de gestion des tâches de build. Task est conçu pour simplifier et automatiser les processus de build, ce qui en fait un outil précieux dans le domaine du développement logiciel.
Qu’est-ce que Task ?
Task est un outil open source qui permet de définir, configurer et exécuter des tâches de manière efficace. Il s’agit d’un outil polyvalent qui peut être utilisé pour automatiser une grande variété de tâches liées au développement, telles que la compilation de code, la génération de documentation, le déploiement de logiciels et bien plus encore. Task est particulièrement apprécié pour sa simplicité d’utilisation et sa flexibilité.
Rôle de Task dans le processus de développement
Task joue un rôle important dans le processus de développement en automatisant les tâches répétitives et en garantissant la cohérence des opérations. Au lieu d’exécuter manuellement une série de commandes pour construire, tester et déployer un projet, les développeurs peuvent définir ces tâches dans un fichier Task et les exécuter en un seul appel de commande.
L’utilisation de Task permet de gagner du temps, d’éviter les erreurs humaines et de rendre le processus de développement plus efficace. Il favorise également la collaboration en permettant aux équipes de travailler avec des configurations de build standardisées.
Installation de Task
Dans cette section, nous aborderons les étapes nécessaires à l’installation de Task sur différentes plateformes.
Installation sur Windows
Pour installer Task sur Windows, vous pouvez suivre ces étapes simples :
-
Téléchargez l’exécutable : Rendez-vous sur la page de téléchargement officielle de Task et téléchargez la dernière version de l’exécutable Windows.
-
Ajoutez Task au PATH : Une fois téléchargé, placez l’exécutable Task dans un répertoire de votre choix, puis ajoutez ce répertoire au PATH de votre système. Cela vous permettra d’exécuter Task depuis n’importe quel emplacement dans l’invite de commandes.
-
Vérifiez l’installation : Ouvrez une invite de commandes et exécutez la commande suivante pour vérifier que Task a été installé avec succès :
Terminal window task --version
Vous devriez voir la version de Task s’afficher à l’écran, ce qui confirme que l’installation a été réalisée avec succès sur votre système Windows.
Installation sur macOS
L’installation de Task sur macOS est également simple :
-
Utilisation avec Homebrew : Si vous utilisez Homebrew, vous pouvez installer Task en exécutant la commande suivante dans votre terminal :
Terminal window brew install go-task/tap/go-task -
Installation manuelle : Si vous préférez une installation manuelle, rendez-vous sur la page de téléchargement officielle de Task, téléchargez la dernière version pour macOS et placez l’exécutable dans un répertoire de votre choix. Assurez-vous également d’ajouter ce répertoire au PATH de votre système.
-
Vérifiez l’installation : Pour vérifier que Task est bien installé, ouvrez un terminal et exécutez la commande suivante :
Terminal window task --version
Installation sur Linux
L’installation de Task sur Linux dépend de la distribution que vous utilisez. Voici comment l’installer sur certaines des distributions Linux populaires :
-
Ubuntu/Debian : Vous pouvez utiliser le gestionnaire de paquets APT pour installer Task avec la commande suivante :
Terminal window sudo apt install task -
Fedora : Sur Fedora, utilisez DNF pour l’installation :
Terminal window sudo dnf install task -
Arch Linux : Pour Arch Linux, utilisez Pacman pour l’installation :
Terminal window sudo pacman -S task
Une fois Task installé sur votre distribution Linux, vérifiez l’installation en exécutant la commande :
task --version
Cela devrait afficher la version de Task installée sur votre système.
Premiers pas avec Task
Pour l’utiliser il faut créer un fichier au format Yaml se nommant
Taskfile.yml
. Je vous rassure pour le créer il suffit d’utiliser la commande
suivante :
task --init
Qui contient ceci :
# https://taskfile.dev
version: '3'
vars: GREETING: Hello, World!
tasks: default: cmds: - echo "{{.GREETING}}" silent: true
Cet exemple contient les mots clés essentiels :
vars:
permet de déclarer des variables qui sont ensuite utilisé entre accolade avec le nom précédé d’un point :{{.variable}}
default:
la tache par défautcmds:
les commandes à exécutersilent
masque la commande ou pas
Pour l’exécuter, il suffit de taper task
sans aucune option puisqu’elle
contient une task default :
taskHello, World!
Pour lister les taches, il suffit de taper task --list
. Les taches listées ne
sont que celles contenant un descripteur desc:
. Cela permet de cacher
certaines qui sont en par exemple dépendantes d’autres.
L’option --help
comme toujours affiche toutes les options :
task --helpUsage: task [-ilfwvsd] [--init] [--list] [--force] [--watch] [--verbose] [--silent] [--dir] [--taskfile] [--dry] [--summary] [task...]
Runs the specified task(s). Falls back to the "default" task if no task namewas specified, or lists all tasks if an unknown task name was specified.
Example: 'task hello' with the following 'Taskfile.yml' file will generate an'output.txt' file with the content "hello".
'''version: '3'tasks: hello: cmds: - echo "I am going to write a file named 'output.txt' now." - echo "hello" > output.txt generates: - output.txt'''
Options: -c, --color colored output. Enabled by default. Set flag to false or use NO_COLOR=1 to disable (default true) -C, --concurrency int limit number tasks to run concurrently -d, --dir string sets directory of execution --dry compiles and prints tasks in the order that they would be run, without executing them -f, --force forces execution even when the task is up-to-date -h, --help shows Task usage -i, --init creates a new Taskfile.yml in the current folder -l, --list lists tasks with description of current Taskfile -o, --output string sets output style: [interleaved|group|prefixed] -p, --parallel executes tasks provided on command line in parallel -s, --silent disables echoing --status exits with non-zero exit code if any of the given tasks is not up-to-date --summary show summary about a task -t, --taskfile string choose which Taskfile to run. Defaults to "Taskfile.yml" -v, --verbose enables verbose mode --version show Task version -w, --watch enables watch of the given task
Comme vous pouvez le voir c’est très complet. La plus importante des options est
-t
permettant de spécifier un fichier de tâche n’ayant pas le nom par défaut
Taskfile.yml
.
Syntaxe de Taskfile.yml
La syntaxe est assez simple et le mieux pour apprendre est de prendre un exemple courant gérer une image docker.
version: '3'
vars: CONTAINER_IMAGE: artefacts.robert.local/python
tasks: build: desc: Construction de l'image Docker cmds: - docker build -t {{.CONTAINER_IMAGE}} -f Dockerfile .
Ici comme il n’y a pas de tache default
, il faut indiquer son nom derrière
task
pour l’exécuter :
tasktask: Task "default" not found
task --listbuild:
task buildunable to prepare context: unable to evaluate symlinks in Dockerfile path: lstat /home/vagrant/Projets/perso/aws-blog/Dockerfile: no such file or directorytask: Failed to run task "build": exit status 1
Ça ne fonctionne pas normal, car il n’y pas de fichier Dockerfile dans le répertoire.
Ajoutons plus de taches avec une image python permettant de lancer les différents outils de test/coverage:
version: '3'
vars: CONTAINER_IMAGE: artefacts.robert.local/python CONTAINER_VERSION: 0.1
tasks: build: desc: Construction de l'image Docker cmds: - docker build -t {{.CONTAINER_IMAGE}}:{{.CONTAINER_VERSION}} -f Dockerfile . exec: desc: Execute le container cmds: - docker run --rm {{.CONTAINER_IMAGE}}
Mon Dockerfile nécessitant buildkit :
FROM python:3.9-slim as builderRUN <<EOF set -o errexit apt update apt install --no-install-recommends build-essential -y apt clean rm -rf /var/lib/apt/lists/*EOF
WORKDIR /srcCOPY Pipfile ./COPY pip.conf /root/.config/pip/pip.confRUN <<EOF echo "export PATH=/root/.local/bin:${PATH}" >> "${HOME}/.bashrc" pip install --no-cache-dir pipenv==2021.11.15 pipenv lock && pipenv install --system --deploy --threeEOF
Le Pipfile:
[[source]]url = "https://pypi.org/simple"verify_ssl = truename = "pypi"
[packages]flake8 = "==4.0.1"greenlet = "==1.1.2"Jinja2 = "==3.0.1"selinux = "== 0.2.1"tenacity = "==8.0.1"yamllint = "==1.26.3"twine = "==3.6.0"coverage= "==6.1.2"pytest = "==6.2.5"pip-tools = "==6.4.0"wheel = "==0.37.0"setuptools = "==57.5.0"
[dev-packages]
[requires]python_version = "3.9"
utilisations de variables d’environnements
Il est possible de faire appel à des variables d’environnement du type dotenv
:
CONTAINER_IMAGE = artefacts.robert.local/python
CONTAINER_VERSION = 0.1
Pour y accéder il suffit d’utiliser la clé env:
et dotenv
:
version: '3'
env: ENV: testing
dotenv: ['.env', '{{.ENV}}/.env.', '{{.HOME}}/.env']
tasks: build: desc: Construction de l'image Docker cmds: - docker build -t {{.CONTAINER_IMAGE}}:{{.CONTAINER_VERSION}} -f Dockerfile . exec: desc: Execute le container cmds: - docker run --rm {{.CONTAINER_IMAGE}}
Inclure d’autres fichiers Taskfile
Il suffit d’utiliser la clé include
avec le chemin du fichier :
version: '3'
env: ENV: testing
dotenv: ['.env', '{{.ENV}}/.env.', '{{.HOME}}/.env']
includes: docker: ./DockerTasks.yml
version: '3'
tasks: build: desc: Construction de l'image Docker cmds: - docker build -t {{.CONTAINER_IMAGE}}:{{.CONTAINER_VERSION}} -f Dockerfile . exec: desc: Execute le container cmds: - docker run --rm {{.CONTAINER_IMAGE}}
Par contre, cela va transformer l’appel.
task --listtask: Available tasks for this project:* docker:build: Construction de l'image Docker* docker:exec: Execute le container
task docker:build
Un include
peut être optionnel :
version: '3'
env: ENV: testing
dotenv: ['.env', '{{.ENV}}/.env.', '{{.HOME}}/.env']
includes: docker: ./DockerTasks.yml optional: true
Spécifier le répertoire de travail
L’option dir
permet de définir le répertoire d’exécution d’une tache :
version: '3'
tasks: build: desc: Construction de l'image Docker dir: Docker cmds: - docker build -t {{.CONTAINER_IMAGE}}:{{.CONTAINER_VERSION}} -f Dockerfile . exec: desc: Execute le container cmds: - docker run --rm {{.CONTAINER_IMAGE}}
J’ai créé un répertoire Docker et j’y ai déplacé le Dockerfile dedans. Cela
permet de limiter rapidement ce qui est inclus dans l’image sans recourir à un
.dockerignore
.
Rendre des tâches dépendantes
On aimerait que la tache exec
dépende de celle du build. Rien de plus simple
ajoutons l’option deps:
version: '3'
tasks: build: desc: Construction de l'image Docker dir: Docker cmds: - docker build -t {{.CONTAINER_IMAGE}}:{{.CONTAINER_VERSION}} -f Dockerfile . exec: deps: [build] desc: Execute le container cmds: - docker run --rm {{.CONTAINER_IMAGE}}
Lançons pour tester :
task docker:exectask: [docker:build] docker build -t artefacts.robert.local/python:0.1 -f Dockerfile .[+] Building 1.2s (2/3)[+] Building 2.3s (2/3)
Pour lancer plusieurs taches dépendantes, il faut les séparer par des virgules :
version: '3'
tasks: build: desc: Construction de l'image Docker dir: Docker cmds: - docker build -t {{.CONTAINER_IMAGE}}:{{.CONTAINER_VERSION}} -f Dockerfile . exec: deps: [build] desc: Execute le container cmds: - docker run --rm {{.CONTAINER_IMAGE}} push: desc: Pousse l'image dans nexus deps: [build, exec] cmds: - docker login -u {{.ARTEFACT_USER}} -p {{.ARTEFACT_PASSWD}} - docker push {{.CONTAINER_IMAGE}}:{{.CONTAINER_VERSION}}
Un autre moyen d’utiliser dans cmds
des appels à d’autres taches :
version: '3'
tasks: build: desc: Construction de l'image Docker dir: Docker cmds: - docker build -t {{.CONTAINER_IMAGE}}:{{.CONTAINER_VERSION}} -f Dockerfile . exec: desc: Execute le container cmds: - task: build - docker run --rm {{.CONTAINER_IMAGE}} push: desc: Pousse l'image dans nexus cmds: - task: build - task: exec - docker login -u {{.ARTEFACT_USER}} -p {{.ARTEFACT_PASSWD}} - docker push {{.CONTAINER_IMAGE}}:{{.CONTAINER_VERSION}}
variables dynamiques
Il est possible rendre dynamique des variables, en utilisant un appel à un shell script. Par exemple, on aimerait taguer notre image avec le short commit git :
version: '3'
tasks: build: desc: Construction de l'image Docker dir: Docker cmds: - docker build -t {{.CONTAINER_IMAGE}}:{{.CONTAINER_VERSION}} -f Dockerfile . vars: CONTAINER_VERSION: sh: git rev-parse --short HEAD exec: desc: Execute le container cmds: - task: build - docker run --rm {{.CONTAINER_IMAGE}} push: desc: Pousse l'image dans nexus cmds: - task: build - task: exec - docker login -u {{.ARTEFACT_USER}} -p {{.ARTEFACT_PASSWD}} - docker push {{.CONTAINER_IMAGE}}:{{.CONTAINER_VERSION}}
Un autre moyen est l’utilisation des arguments de tache avec l’utilisation de — derrière le nom de la tache.
version: '3'
tasks: pip: cmds: - pip {{.CLI_ARGS}}
L’appel est de ce type :
task pip -- 'install -r requirements.txt'
Variables spéciales
Task possède quelques variables qui peuvent être utile.
OS
pouvant prendre les valeurs : “windows”, “linux”, “darwin” ou “freebsd”
ARCH
pouvant prendre les valeurs : “386”, “amd64”, “arm” ou “s390x”
Exemple d’utilisation :
version: '3'
includes: build: ./Taskfile_{{OS}}.yml
Variables sur plusieurs lignes
Une syntaxe parfois utile pour les variables :
vars: CONTENT: | foo bar
Utilisation du système de templating Go
On peut aussi, un peu avec Ansible
et Jinja
utiliser le système de template
Go ↗.
version: '3'
tasks: print-date: cmds: - echo {{now | date "2006-01-02"}}
Avantages de l’utilisation de Task
L’utilisation de Task présente de nombreux avantages pour les développeurs et les équipes de développement. Quelques-uns de ces avantages clés sont les suivants :
- Automatisation : Task permet d’automatiser les tâches de build, ce qui réduit le travail manuel et les risques d’erreur.
- Flexibilité : Task est flexible et peut être adapté aux besoins spécifiques de chaque projet.
- Portabilité : Les fichiers Task peuvent être partagés avec l’équipe, ce qui rend la configuration de build cohérente sur toutes les machines.
- Documentation vivante : Les fichiers Task servent également de documentation vivante pour les tâches de build, ce qui facilite la compréhension et la maintenance du code.
Conclusion
Dans cette documentation, nous avons exploré en détail l’outil de build Task, en commençant par son introduction et son installation sur différentes plateformes. Nous avons ensuite plongé dans la structure d’un fichier Task, comprenant comment définir des tâches, des descriptions, des commandes et des dépendances.
Task se révèle être un outil puissant pour automatiser les tâches de build, améliorant ainsi l’efficacité du processus de développement. Sa flexibilité et sa facilité d’utilisation en font un choix judicieux pour les développeurs et les administrateurs systèmes.
Si vous voulez voir des exemples d’utilisation, il suffit de rechercher sur github ↗ comme celui-ci : ProfessorManhattan ↗