Sortie de Bundler 1.0.0

Posté par (page perso) . Modéré par Benoît Sibaud.
Tags :
10
30
août
2010
Ruby
Bundler permet de gérer les dépendances d'une application Ruby au cours de sa vie sur plusieurs machines de manière systématique et reproductible. Cette application sous licence MIT vient de sortie en version 1.0.

Bundler peut être utilisé conjointement à Ruby Version Manager pour les développeurs travaillant sur de nombreux projets, mais il est déjà très utile par lui-même. Je vous invite à lire la seconde partie de la dépêche pour comprendre comment bundler peut vous rendre service. Dans le monde Ruby, les bibliothèques sont généralement packagées sous forme de gems mises à disposition sur Rubygems.org. L'outil en ligne de commande gem permet alors de les installer facilement, ainsi que de gérer les dépendances. Enfin, un require "rubygems" permet aux applications Ruby de pouvoir charger ces gems.

Une des particularités de rubygems est la possibilité d'avoir plusieurs versions d'une même gem installées en parallèle. Ce n'est pas gênant car rubygems gère les dépendances... enfin, en théorie. Par exemple, si mon application est écrite avec le framework Ruby on Rails, elle va commencer par charger Rails et ses dépendances. Rack, une des dépendances en question, va être chargé à la version la plus récente compatible avec Rails, disons la version 1.2.1. Un peu plus loin dans le code, l'application va charger le greffon rack-proctitle. Si, par malheur, ce greffon ne fonctionne qu'avec les versions 1.1 de rack, rubygems va lever une exception can't activate rack (= 1.1.0, runtime) for [], already activated rack-1.2.1. Très frustrant, non ?

Rubygems permet également d'installer des exécutables. Par exemple, Ruby on Rails vient avec un exécutable rails qui permet de démarrer un projet. Là encore, avoir plusieurs versions de rails en parallèle pose problème : après avoir installé une version de Rails 3, vous ne pouvez plus commencer de projets en Rails 2.3 car l'exécutable a été écrasé. Pas terrible ?

Enfin, il est assez difficile de s'assurer que les mêmes gems sont installées sur plusieurs environnements. Par exemple, je déploie une application sur un serveur de test, je vérifie que tout va bien, puis je fais le déploiement en production. Si entre les déploiements, une nouvelle version d'une gem utilisée est sortie, je risque fort de me retrouver avec des versions différentes de cette gem sur les deux environnements, ce qui n'est pas idéal.

Bundler a été écrit pour corriger ces problèmes. Il travaille avec deux fichiers par application : Gemfile et Gemfile.lock. Le développeur listera dans le premier la liste des dépendances de son application. Puis bundler générera le second avec la liste précise de tous les gems à utiliser et de leur version après avoir calculé l'arbre de toutes les dépendances.

Pour installer le projet sur une nouvelle machine, c'est alors très simple, il suffit de lancer bundle install. Cela installe les gems à la version indiquée dans le fichier Gemfile.lock. Pour le développeur, ce n'est guère plus compliqué, il lui suffit de faire un bundle update après chaque modification du Gemfile pour que celle-ci soit prise en compte.

Bundler va également pouvoir montrer que les gems présents dans le fichier Gemfile à l'application et à rubygems. Ainsi, à l'exécution, il n'y aura plus le risque de charger une mauvaise version.

Enfin, bundle exec résout le dernier problème présenté, à savoir lancer l'exécutable qui correspond bien à la version souhaitée du gem en question. Par exemple, bundle exec rails en présence d'un Gemfile.lock indiquant Rails 2.3.8 créera bien un projet pour Rails 2.3, et ce même si Rails 3 est installé par ailleurs.

Ainsi se finit notre découverte de Bundler, mais sachez que celui-ci offre également des fonctionnalités plus avancées (gestion des groupes de dépendances, options pour le déploiement, aide au debug, etc.).
  • # .

    Posté par (page perso) . Évalué à 2.

    Ma feature préférée dans Bundler, c'est qu'il est vraiment aisé de poser une dépendance d'une librairie sur un répo Git. Imaginons vous développez une appli avec une librairie X, un jour cette librairie X à un bug critique pour votre appli ou une nouvelle killer feature pas encore releasée.
    Vous pouvez avec Bundler, indiquer que vous voulez utiliser cette librairie depuis son repo Git si la librairie a été patchée depuis. Et si vous écrivez vous même le patch, il est facile de forker le repo...
    • [^] # Re: .

      Posté par . Évalué à 3.

      c'est effectivement une feature "intéressante" mais pour ce type d'appli elle n'est pas fondamentale, pour la simple et bonne raison que Bundler est fait pour aider à la distribution d'un logiciel, en gérant au mieux (et là, c'est vraiment génial dans Bundler) les dépendances, et qu'on ne devrait JAMAIS distribuer un logiciel "stable" dépendant d'un dépot git qui par définition est constamment mouvant. Il n'y a bien que dans la communauté ruby qu'on n'oublie cette règle dont le seul but est la protection des utilisateurs (déboguer les problèmes quand on dépend d'un logiciel "mouvant" c'est l'enfer).

      Evidemment, il suffit de distribuer un logiciel avec une utilisation correcte de Bundler quand on release une version "stable". Cependant, mon expérience avec Ruby est que c'est un enfer de maintenir une machine stable qui utilise Ruby intensivement (serveur d'applis rails), parce que la moitié des projets ruby ne releasent JAMAIS de tarballs versionnés et il n'y a qu'un dépot git (merci GitHub pour ça...)
      • [^] # Re: .

        Posté par (page perso) . Évalué à 2.

        dépendant d'un dépot git qui par définition est constamment mouvant.

        Le dépôt Git peut bouger, voir théoriquement casser ton application, mais lorsque tu installes le bundle, Bundler génère un fichier Gemfile.lock. Ce fichier est locké sur des versions précises des gems et un numéro de révision pour les dépôts Git. Tant que tu n'utilises pas "bundle update" pour mettre à jour ton fichier Gemfile.lock, tu es sûr que ton application fetchera toujours les mêmes versions des gems et des dépôts Git.
        D'ailleurs c'est pour cette raison que versionner Gemfile.lock est essentiel, c'est même obligatoire pour utiliser l'option "--deployment".

        Grâce à cette fonctionnalité de Bundler, je ne vois aucun inconvénient à utiliser des dépôts Git, même pour un projet ou une librairie stable (si cela est nécessaire bien sûr).
      • [^] # Re: .

        Posté par (page perso) . Évalué à 1.

        De plus,
        tu utilises beaucoup le mot "stable" dans ton commentaire.

        Chaque développeur a sa définition du mot "stable", certaines librairies sont très stables en master et leurs développeurs ne releasent pas souvent de nouvelles gems, et d'autres c'est l'inverse.

        Lorsque tu développes une application Ruby avec des dizaines de gems, utiliser constamment les versions stables des gems n'est pas forcément la meilleure chose, tout comme utiliser toutes les gems en branche "master".
        C'est pour cette raison que la philosophie de Bundler laissant le choix au développeur de setter ses dépendances sur une release officielle considérée "stable" ou un dépôt est selon moi bonne.

        La seule chose qui compte c'est que les tests unitaires/fonctionnels pour TON application passent pour une version donnée de chaque librairie utilisée (que celle ci soit considérée stable ou instable par son auteur n'a aucune valeur).
  • # Inutile

    Posté par . Évalué à 3.

    s/répétable/reproductible/

    Processus répétable : qu’on peut appliquer plusieurs fois (taper sur le clou, taper sur le clou, …).

    Processus reproductible : qu’on peut appliquer dans les mêmes conditions pour avoir les mêmes effets (enfoncer un clou).

    Sinon, Pete and Repeat are on boat…

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.