80 votes

Dois-je spécifier les versions exactes dans mon Gemfile ?

J'ai remarqué que sur rubygems.org beaucoup de gemmes suggèrent que vous les spécifiez par version majeure plutôt que par version exacte. Par exemple...

Le joyau du jambon-rails ...

gem "haml-rails", "~> 0.3.4"  # "$ bundle install" will acquire the 
                              # latest version before 1.0.

Cependant, sur la base de la Documentation sur le Bundler il me semblait qu'il serait préférable de déterminer la version exacte comme ceci...

gem "haml-rails", "0.3.4"

Voilà donc votre gemme haml-rails et toutes ses dépendances ne dériveront pas vers l'avant. Si vous vérifiez le projet sur une autre machine quelques semaines plus tard et exécutez $ bundle install vous aurez exactement les mêmes versions de tout ce que vous avez spécifié.

J'ai vu des versions ponctuelles casser des choses, et je pensais qu'une partie de l'idée de Bundler était de " Bundle.lock " toutes vos versions de gemmes.

Mais sur rubygems.org ils utilisent beaucoup "~>" alors peut-être que je manque quelque chose ?

Toute clarification me serait très utile pour comprendre Bundler et la gestion des gemmes.

0 votes

Je le ferais. Moins il y a de surprises, mieux c'est. Il suffit d'une seule fois qu'une dépendance se mette à jour sans que vous le fassiez intentionnellement pour vous envoyer dans un trou de lapin pendant des heures, voire des jours, pour que vous appreniez cette leçon. On ne peut pas faire confiance aux bibliothèques tierces et open-source pour suivre strictement le versionnement sémantique (même mes propres bibliothèques). Le risque n'en vaut pas la peine.

60voto

Abe Voelker Points 7306

C'est le but du fichier Gemfile.lock - exécuter bundle install avec un Gemfile.lock présent n'installe qu'en utilisant les dépendances qui y sont listées ; il ne résout pas le Gemfile. Pour mettre à jour les dépendances / mettre à jour les versions des gemmes, vous devez alors explicitement faire un bundle update qui mettra à jour votre fichier Gemfile.lock.

S'il n'y avait pas de Gemfile.lock, le déploiement du code en production serait un problème majeur car, comme vous le mentionnez, les dépendances et les versions des gemmes pourraient changer.

En bref, vous devriez être généralement en sécurité en utilisant l'opérateur de contrainte de version pessimiste ( ~> ) comme rubygems.org le conseille. Assurez-vous simplement de réexécuter vos tests après avoir fait un bundle update pour s'assurer que rien ne se casse.

Il y a un bel article par Yehuda Katz qui a un peu plus d'informations sur Gemfile.lock.

1 votes

OK, donc les gemmes restent à leurs versions établies enregistrées dans Gemfile.lock. Alors quel est le but d'ajouter "~>" ? En quoi cela est-il avantageux ?

2 votes

@ethan RubyGems a un doc qui l'explique (voir la section "Preventing Version Catastrophe"). L'essentiel est que seul le dernier nombre entier du numéro de version peut être augmenté (par exemple, '~> 1.0.5' permet de mettre à jour vers la version 1.0.9999, mais jamais vers 1.1.x). Le mécanisme permet aux gemmes d'être mises à jour, mais sans introduire d'incompatibilités qui pourraient casser des choses (cela suppose que les gemmes suivent la politique de "Versionnement rationnel" que le lien décrit).

3 votes

Je pense que l'essentiel de ce que vous avez écrit est que l'on devrait garder des contraintes de version pessimiste dans sa vie quotidienne. Gemfile donc un peut mettre facilement à niveau vers la dernière version qui correspond à la fois à la version majeure et mineure spécifiée. Mais le Gemfile.lock doit également être utilisé, et conservé dans les sources, de sorte que les mises à jour doivent être effectuées explicitement pour affecter tout environnement dans lequel votre code est déployé.

15voto

Augy Points 62

TL;DR

Oui, utilisez verrouillage pessimiste ( ~> ) et spécifier un version sémantique jusqu'à la parcelle ( Major.minor.patch ) sur tous vos joyaux !

Discussion

Je suis surpris par le manque de clarté sur cette question, même les "experts du secteur" m'ont dit l'autre jour que Gemfile.lock est là pour maintenir les versions des gemmes. C'est faux !

Vous voulez organiser votre Gemfile de manière à ce que vous puissiez exécuter bundle update à tout moment sans risquer de tout casser. Pour y parvenir :

  1. Spécifiez une version de niveau patch pour toutes vos gemmes avec un verrouillage pessimiste. Ceci permettra bundle update pour vous donner des correctifs, mais pas de changements de rupture.

  2. Indiquez un ref pour les gemmes de git

Le seul inconvénient de cette configuration est que lorsqu'une nouvelle version mineure/majeure d'une gemme est publiée, vous devez mettre la version à jour manuellement.

Scénario d'alerte

Pensez à ce qui se passe si vous ne verrouillez pas vos pierres précieuses.
Vous avez un appareil non verrouillé gem "rails" dans votre gemfile et la version dans Gemfile.lock es 4.1.16 . Vous êtes en train de coder et à un moment donné, vous faites un bundle update . Maintenant, votre version de Rails passe à 5.2.0 (à condition qu'une autre gemme ne l'empêche pas) et tout se casse la figure.
Faites-vous une faveur et ne permettez pas cela pour n'importe quel bijou !

Un exemple de Gemfile

# lock that bundler
if (version = Gem::Version.new(Bundler::VERSION)) < Gem::Version.new('1.16.3')
  abort "Bundler version >= 1.16.3 is required. You are running #{version}"
end

source "http://rubygems.org"

# specify explicit ref for git repos
gem "entity_validator",
  git: "https://github.com/plataformatec/devise",
  ref: "acc45c5a44c45b252ccba65fd169a45af73ff369" # "2018-08-02"

# consider hard-lock on gems you do not want to change one bit
gem "rails", "5.1.5"

# pessimistic lock on your common gems
gem "newrelic_rpm", "~> 4.8.0"
gem "puma", "~> 3.12.0"

group :test do
  gem "simplecov", "~> 0.16.1", require: false
end

Une concession
Si vous êtes sûr que vos tests vont attraper les bogues introduits par les changements de version des gemmes, vous pouvez essayer de verrouiller les gemmes de façon pessimiste à la version mineure, et non au patch.
Cela permettra à la version de la gemme d'augmenter dans la version majeure spécifiée, mais jamais dans la suivante.

gem "puma", "~> 3.12"

7voto

MrDanA Points 6685

Je dirais certainement d'utiliser les numéros de version exacts. Vous pouvez probablement toujours vous contenter d'une version majeure, ou ne jamais spécifier de version, et tout ira bien, mais si vous voulez vraiment ce niveau de contrôle fin et avoir une confiance totale dans votre programme lorsqu'il est exécuté sur d'autres machines, utilisez les numéros de version exacts.

J'ai été dans des situations où le numéro de version exact n'était pas spécifié, et quand moi ou quelqu'un d'autre a fait une bundle install le projet s'est cassé parce qu'il est passé à une version plus récente. Cela peut être particulièrement grave lors du déploiement en production.

Regroupement fait verrouille les spécifications de vos gemmes, mais si vous lui demandez d'utiliser une version majeure, il le fait. Donc il sait juste "Oh la version est verrouillée à > 0.1" ou autre, mais pas "Oh la version est verrouillée spécifiquement à 0.1.2.3".

13 votes

Si Gemfile.lock est présent, alors Bundler sait, en fait, quelle version spécifique installer (c'est pourquoi Gemfile.lock doit être stocké dans le répertoire aux côtés de Gemfile ).

3 votes

Faire un bundle update <gem> mais vous pouvez finir par mettre à jour beaucoup plus de choses que vous ne le pensiez, même si les Gemfile.lock est présent, et cela peut être une situation dangereuse et délicate.

1 votes

Je suis d'accord avec la recommandation de RubyGems eux-mêmes sur cette question : Utilisez simplement la contrainte pessimiste (~>). Cela encourage l'ensemble de la communauté à s'emparer du versionnage sémantique, ce qui est une bonne chose, et entre cela et les fonctionnalités intégrées de stabilité de Gemfile.lock, vos bases devraient être plus que couvertes.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X