# Fini le bordel de vos versions locales : découvrez ASDF

Vous êtes-vous déjà retrouvés dans cette situation où vous travaillez sur plusieurs projets utilisant des versions différentes de Java, NodeJS ou Postgres ? Dans cet article, nous allons découvrir comment changer automatiquement de version en fonction du dossier courant (et donc du projet). 📁

## Mise en Situation

En tant que développeur, il vous est peut-être déjà arrivé de travailler sur plusieurs projets à la fois pour différents clients (ou pour le même client), et vous avez probablement rencontré ce cas de figure : le projet A utilise Java 8, le projet B utilise Java 11, et le projet C utilise Java 17. Pour passer rapidement d'une version à une autre, vous avez peut-être utilisé la commande `update-alternatives`.

```bash
sudo update-alternatives --config java
```

Cette méthode fonctionne bien, mais elle comporte un inconvénient : vous devez la lancer manuellement à chaque fois que vous voulez passer à une autre version, ce qui peut vite devenir pénible. De plus, elle ne fonctionne pas avec d'autres outils tels que `node` ou `postgres`.

Une solution à ce problème serait d'utiliser Docker. En effet, le but de Docker est de pouvoir créer une image qui comporte toutes les bonnes versions à utiliser pour le projet courant. Cependant, tout le monde ne sait pas utiliser Docker et tous les projets ne contiennent pas de Dockerfile pour mettre en place cet environnement. De plus, il n’est pas très pratique d’avoir à utiliser Docker à chaque fois qu’il faut lancer une commande (récupération de la configuration, de l’environnement d’exécution, etc).

Une autre solution serait d'avoir une sorte de baguette magique qui pourrait automatiquement sélectionner la bonne version à utiliser en fonction du projet, par exemple Java 8 pour le projet A, Java 11 pour le projet B, et ainsi de suite.

Eh bien, comment dire... cette baguette magique existe, et elle s'appelle [asdf](https://asdf-vm.com/). 🪄

## ASDF : Notre Baguette Magique

`asdf`, qu'est-ce que c'est concrètement ? C'est un outil en ligne de commande (CLI) qui sélectionne automatiquement la bonne version à utiliser (Java, NPM, Node, Postgres, PHP, et bien plus encore) en fonction du dossier dans lequel on se trouve. Pour déterminer la version de chaque outil à utiliser, `asdf` utilise un fichier nommé `.tool-versions` qui se trouve dans les dossiers concernés. Ce fichier comporte simplement une association entre chaque outil et sa version correspondante.

```plaintext
java openjdk-17
nodejs 17.3.0
postgres 13.5
```

Lorsque votre dossier courant ne contient pas ce fichier, `asdf` va alors chercher dans les dossiers parents afin de trouver le premier qui en contient un. De ce fait, vous devez spécifier une version par défaut pour chaque outil, qui sera utilisée si `asdf` ne parvient pas à trouver de fichier `.tool-versions` dans les dossiers parents. Les versions par défaut sont stockées dans votre répertoire personnel : `~/.tool-versions`.

Un point intéressant à noter est que ce fichier peut être commité sur `git` afin que vos collègues puissent également avoir les bonnes versions à utiliser, pourvu qu'ils utilisent eux aussi `asdf`. 💪🏼

## Un Exemple

Supposons que notre version par défaut de `node` soit la version 17.3.0, mais que l'un des projets sur lequel on travaille date de plusieurs années et utilise la version 12.13.0. Si on lance un terminal et qu'on exécute la commande permettant de récupérer la version de `node`, nous aurons notre version actuelle.

```plaintext
$ node --version
v17.3.0
```

Cette commande produira la même sortie si l'on se déplace dans le dossier `projet-A` ou dans n'importe quel autre dossier. En revanche, si on indique à `asdf` que pour ce projet la version à utiliser est 12.13.0, alors la sortie de cette commande sera différente.

```plaintext
$ asdf set nodejs 12.13.0
$ node --version
v12.13.0
```

Et si l'on se déplace à nouveau dans un autre dossier, la version de `node` va revenir comme par magie à celle par défaut.

```plaintext
$ cd ..
$ node --version
v17.3.0
```

Bluffant, pas vrai ? 🤯 Découvrons maintenant comment mettre en place `asdf` (spoiler : c'est ridiculement simple).

## Mettre en Place ASDF

Tout d'abord, nous allons devoir télécharger `asdf` (disponible sur Linux et MacOS, mais malheureusement pas sur Windows). Pour ce faire, nous clonons le dépôt `git` dans notre dossier personnel.

```plaintext
git clone https://github.com/asdf-vm/asdf.git ~/.asdf
```

> Si vous êtes sur MacOS, vous pouvez simplement utiliser `brew`.
> 
> ```plaintext
> brew install asdf
> ```

Une fois le dépôt cloné, nous devrons ajouter les deux lignes ci-dessous à notre fichier `.bashrc` (ou `.zshrc`).

```plaintext
. $HOME/.asdf/asdf.sh
. $HOME/.asdf/completions/asdf.bash
```

Et c'est tout ! Nous avons installé `asdf` avec succès. 🎉

## Utilisation

Pour utiliser `asdf`, nous allons ajouter les plugins dont nous aurons besoin. Un plugin correspond à un outil : par exemple, nous avons besoin du plugin `java` pour passer d'une version de `java` à une autre, du plugin `nodejs` pour changer de version de NodeJS, et ainsi de suite. Pour ajouter un plugin, il suffit de lancer la commande suivante :

```plaintext
asdf plugin add [plugin]
```

Dans notre exemple, nous allons continuer avec NodeJS. On installe donc le plugin `nodejs`.

```plaintext
asdf plugin add nodejs
```

> La commande `asdf plugin list all` permet d'afficher la liste de tous les plugins disponibles. Comme la liste est particulièrement longue, on filtrera les résultats avec `grep`.
> 
> ```plaintext
> asdf plugin list all | grep node
> ```

Maintenant que nous avons ajouté le plugin `nodejs`, nous aurons besoin de télécharger les versions que nous utilisons. Dans notre cas, il s'agit des versions 12.13.0 et 17.3.0.

```plaintext
asdf install nodejs 12.13.0
asdf install nodejs 17.3.0
```

Après avoir installé ces versions, la dernière étape consiste à indiquer à `asdf` quelle version utiliser en fonction du projet. Pour ce faire, on se rend dans le dossier de notre projet qui utilise la version 12.13.0 et on choisit la bonne version de `nodejs` à utiliser.

```plaintext
asdf set nodejs 12.13.0
```

Et voilà ! La version 12.13.0 de Node sera maintenant utilisée dans le dossier de notre projet, ainsi que dans ses sous-dossiers. 🥳

Si on lance maintenant `ls -al` dans le dossier courant pour afficher la liste des fichiers, on remarque ce fameux fichier `.tool-versions` qui contient la version de Node pour ce projet. Nous pouvons l'ajouter à notre système de contrôle de versions (`git`).

```plaintext
nodejs 12.13.0
```

> Lorsque vos collègues cloneront le dépôt `git` contenant ce fichier, ils n'auront pas à installer manuellement les versions de chaque outil : ils peuvent simplement lancer la commande `asdf install`, et la baguette magique se chargera de télécharger toutes les versions nécessaires.

Enfin, comme nous l'avons vu précédemment, nous devons définir une version par défaut à utiliser lorsqu'on se trouve dans un dossier ne comportant pas de fichier `.tool-versions` (ni dans ses dossiers parents). Dans notre cas, nous allons utiliser la version 17.3.0 comme version par défaut.

```plaintext
asdf set --home nodejs 17.3.0
```

Et c'est terminé, nous nous sommes maintenant débarrassés de l'enfer qu'est le changement manuel de nos versions, et ce grâce à notre nouvelle baguette magique. 🪄

## Conclusion

Les versions de notre environnement sont maintenant gérées automatiquement par `asdf`. Lorsque vous aurez besoin d'utiliser un nouveau plugin, les étapes seront toujours les mêmes :

1. Installer le plugin correspondant : `asdf plugin add [plugin]`
    
2. Installer les versions concernées : `asdf install [plugin] [version]`
    
3. Pour chaque projet, sélectionner la version à utiliser : `asdf set [plugin] [version]`
    
4. Sélectionner la version par défaut pour ce plugin : `asdf set --home [plugin] [version]`
    

Pour plus d'informations, ou si vous avez besoin d'aide concernant cet outil incroyable, n'hésitez-pas à vous rendre sur [asdf-vm.com](https://asdf-vm.com/). De plus, vous pouvez étoiler `asdf` sur [GitHub](https://github.com/asdf-vm/asdf) pour supporter l'équipe derrière ce projet. 😉

J'espère que cet article vous a été utile, et on se donne rendez-vous dans un prochain article. 🤘🏼
