Des Version Manager pour faire cohabiter plusieurs versions d’un langage, SDK et framework

Ruby, Python, Rust, Node.js, Flutter, … Comme tout objet dans le monde, les langages, frameworks et outils sont amenés à changer avec le temps. Version mineur par-ci, version majeure par-là. Comment jongler facilement entre les versions ?

Quand on est développeur, on utilise tout un tas d’outils et de SDK. Parfois sur plusieurs projets, qui utilisent des versions différentes bien évidemment. Je peux avoir besoin de Node.js 19 pour le front web et de Node.js 16 pour le backend. Je peux travailler à la fois sur une app Flutter en Dart 2 et une autre en Dart 3. J’ai peut-être besoin d’une version différente de Python sur mon poste et sur la CI.

Ou parfois sur le même projet avec des branches différentes. Je commence à migrer vers Dart 3 sur une branche, j’ai un bug de prod à corriger il faut que je retourne sur la branche principale qui elle est sous Dart 2.

Si on installe des versions spécifiques à la main, à quoi ressemble notre acrobatie ?

On désinstalle la version X. On télécharge et installe la version Y. On joue avec. On désinstalle la version Y. On télécharge et réinstalle la version X. À chaque étape, c’est un peu de temps perdu. Certains outils sont en plus lourds à télécharger et installer, on se retrouve vite à ouvrir son navigateur ou téléphone et sortir de notre flow :)

C’est là qu’interviennent les outils de gestion de versions.

Principe général

L’idée est simple. Plutôt que d’installer directement la toolchain d’un langage par exemple, on va installer l’outil de gestion de version dédié à tel ou tel langage. Chaque langage a son propre gestionnaire, et ce sont souvent des projets open-source. Ils se reconnaissent facilement à leur nom : ils sont souvent suffixés par Version Manager ou Version Management.

C’est ensuite via le Version Manager que l’on va installer la ou les versions du langage dont on a besoin. Les différentes versions seront installées dans un sous-dossier de l’outil et ne vont pas venir directement s’écraser entre elles dans le dossier /bin (comme ce pourrait être le cas avec une installation classique). On peut ainsi en avoir plusieurs téléchargées et installées sur un poste, directement prêtes à l’emploi.

Une fois qu’on a installé les versions qui nous intéressent, il n’y a plus qu’à indiquer la version par défaut via une simple commande. Et quand on veut changer ? Une commande et c’est opérationnel dans la même seconde. On jongle très facilement avec de multiples versions, branches, projets.

Switch automatique

Mieux encore. On peut aller un cran plus loin avec certains Version Manager : la version utilisée change automatiquement en fonction du projet que l’on ouvre. C’est le cas avec Ruby par exemple. Il suffit de créer un fichier .ruby-version, d’y écrire le numéro de la version (3.2.2), et de le placer dans le dossier racine du projet. Simple, basique.

L’outil de Version Manager détectera ce fichier et changera la version de Ruby utilisée de manière transparente et automatique. On jongle entre des projets et des branches sans aucune adhérence. On voit encore plus la puissance de ces outils ici.

L’intérêt de tels fichiers se retrouve aussi dans le travail en équipe. Le fichier est versionné au sein du projet, ce qui permet à tous les développeurs d’utiliser systématiquement les mêmes versions.

Quelques exemples

Vous en connaissez probablement déjà quelques uns, voire les utilisez. En voici quelques-uns que j’utilise :

La question que vous vous posez peut-être maintenant, c’est est-ce qu’il en existe un seul pour les gouverner tous ? Jusqu’à maintenant, je n’avais pas connaissance d’un Version Manager qui gérait de multiples runtimes. Mais pendant l’écriture de cet article, j’ai effectué de rapides recherches et j’ai découvert des outils. C’est aussi pour ça que j’aime écrire, ça me permet de prendre du recul, de chercher davantage, de trouver de nouvelles choses.

En voici deux : asdf et rtx. Je n’ai fait aucun test pour le moment, mais je compte bien essayer et vous en parler à l’occasion. Si vous avez des retours d’expérience avec ces outils, ou d’autres, je suis preneur.

Contre-parties

Il peut y avoir un peu plus de configs et d’étapes à la première installation d’un Version Manager, versus installer directement le langage/SDK. Pour autant, cela reste relativement court et facile.

Autre effet de bord pour certains Version Manager, il faut parfois exécuter le langage/SDK via l’outil - ils agissent comme un proxy. Par exemple, on tapera la commande fvm flutter test au lieu de flutter test.

De mon point de vue, j’accepte pleinement ces deux points. Je trouve ces inconvénients largement acceptables et plus faibles que les avantages qu’ils apportent - je peux facilement jongler entre des versions, voire le rendre automatique entre mes projets et mes collègues.

Mais, il reste une question en suspens. Qui manage les versions des gestionnaires de versions ? 🙃

Une ouverture parfaite pour vous quitter. J’y réponds quand même avant de ranger ma plume. A priori, le besoin de jongler à ce niveau n’existe pas. Je les ai installés via Homebrew, le gestionnaire de paquet pour macOS, et c’est très bien ainsi.