¿Debo especificar versiones exactas en mi Gemfile?


He notado que en rubygems.org muchas de las gemas sugieren que las especifique por versión principal en lugar de por versión exacta. Por ejemplo...

La gema de haml-rails...

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

Sin embargo, basado en el Bundler docs me pareció que sería mejor precisar la versión exacta como esta...

gem "haml-rails", "0.3.4"

Así que ahí está tu gema haml-rails y todas sus dependencias no se desplazarán hacia adelante. Si revisa el proyecto en una máquina diferente unas semanas más tarde y ejecute $ bundle install tendrá exactamente las mismas versiones de todo lo que especificó.

He visto que los lanzamientos de point rompen cosas, y pensé que parte de la idea de Bundler era "Bundle.lock" todas sus versiones de gema.

Pero en rubygems.org usan "~ > " mucho, así que tal vez me estoy perdiendo algo?

Cualquier aclaración sería muy útil para entender la gestión de Bundler y gem.

Author: Ethan, 2012-02-13

3 answers

Este es el propósito del Gemfile.bloquear archivo-ejecutando bundle install con un Gemfile.lock present solo instala usando las dependencias listadas allí; no vuelve a resolver el Gemfile. Para actualizar dependencias / actualizar versiones de gema, entonces tienes que hacer explícitamente un bundle update, que actualizará tu Gemfile.archivo de bloqueo.

Si no hubiera un Gemfile.bloquear, implementar código en producción sería un problema importante porque, como mencionaste, las dependencias y las versiones de gema podrían cambiar.

En en resumen, debería estar generalmente seguro usando el operador de restricción de versión pesimista (~>) como rubygems.org aconseja. Solo asegúrese de volver a ejecutar sus pruebas después de hacer un bundle update para asegurarse de que nada se rompa.

Hay un buen artículo de Yehuda Katz que tiene un poco más de información sobre Gemfile.bloqueo.

 53
Author: Abe Voelker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-05-01 20:24:09

Definitivamente diría que use los números de versión exactos. Probablemente siempre puede bloquearlo a una versión principal, o nunca especificar ninguna versión, y estar bien, pero si realmente desea ese nivel de control de grano fino y tener 100% de confianza en su programa cuando se ejecuta en otras máquinas, use los números de versión exactos.

He estado en situaciones en las que no se especificó el número exacto de la versión, y cuando yo o alguien más hizo un bundle install, el proyecto se rompió porque fue a un versión más reciente. Esto puede ser especialmente malo cuando se implementa en producción.

Bundler hace bloquear las especificaciones de su gema, pero si le está diciendo que solo use una versión principal, entonces lo bloquea. Así que es solo sabe " Oh la versión está bloqueado en > 0.1 "o lo que sea, pero no"Oh la versión está bloqueado específicamente en 0.1.2.3".

 5
Author: MrDanA,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-13 18:10:28

TL; DR

Sí, use bloqueo pesimista (~>) y especificar una versión semántica hasta parche (Major.minor.patch) en todas sus gemas!

Discusión

Me sorprende la falta de claridad sobre este tema, incluso los "expertos de la industria" me dijeron el otro día que Gemfile.lock está allí para mantener las versiones de gem. Mal!

Desea organizar su Gemfile de tal manera que pueda ejecutar bundle update en cualquier momento sin correr el riesgo de romperse todo. Para lograr esto:

  1. Especifique una versión de nivel de parche para todas sus gemas con bloqueo pesimista. Esto permitirá a bundle update darle correcciones, pero no romper los cambios.

  2. Especifique un ref para gemas de git

El único inconveniente de esta configuración es que cuando sale una nueva versión menor/mayor dulce para una gema, tienes que subir la versión manualmente.

Escenario de advertencia

Considere lo que sucede si no cierras tus gemas.
Tienes un gem "rails" desbloqueado en tu gemfile y la versión en Gemfile.lock es 4.1.16. Estás codificando y en algún momento haces un bundle update. Ahora tu versión de Rails salta a 5.2.0 (siempre que alguna otra gema no lo impida) y todo se rompe.
¡Hazte un favor y no permitas esto para ninguna joya!

Un ejemplo 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

Una concesión
Si estás seguro de que tus pruebas detectarán errores introducidos por gem cambios de versión, puede probar gemas de bloqueo pesimista en la versión menor, no en el parche.
Esto permitirá que la versión de la gema aumente dentro de la versión principal especificada, pero nunca en la siguiente.

gem "puma", "~> 3.12"
 0
Author: Epigene,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-10 14:24:52