Чи повинен я вказати точні версії у своєму Gemfile?


76

Я помітив, що на rubygems.org багато дорогоцінних каменів пропонують вказувати їх за основною версією, а не за точною версією. Наприклад...

Перлина hamm-rails ...

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

Однак, базуючись на документах Bundler, мені здалося, що було б краще зафіксувати саме таку версію ...

gem "haml-rails", "0.3.4"

Отже, є ваш дорогоцінний камінь haml-rails, і всі його залежності не змістяться вперед. Якщо ви перевірите проект на іншій машині через кілька тижнів і запустите, у $ bundle installвас будуть точно такі ж версії всього, що ви вказали.

Я бачив точкові випуски, що розбивають речі, і я думав, що частиною цілої ідеї Bundler було " Bundle.lock" створення всіх ваших версій для самоцвітів.

Але на rubygems.org вони часто використовують "~>", тому, можливо, я чогось пропускаю?

Будь-яке роз'яснення було б дуже корисним для мене в розумінні Bundler та управління коштовностями.


Я б. Чим менше сюрпризів, тим краще. Потрібен лише один раз, коли залежність оновлюється без того, щоб ви навмисно робили це, щоб відправити вас у кролячу нору на години або навіть дні, щоб змусити вас вивчити цей урок. Не можна довіряти стороннім бібліотекам та бібліотекам з відкритим кодом суворо дотримуватися семантичних версій (навіть моїх власних бібліотек). Не варто ризикувати.
Джошуа Пінтер

Відповіді:


59

Це мета файлу Gemfile.lock - запуск bundle installіз Gemfile.lock присутній лише для встановлення з використанням перелічених там залежностей; це не вирішує Gemfile. Щоб оновити залежності / оновити версії gem, вам потрібно явно зробити a bundle update, який оновить ваш файл Gemfile.lock.

Якби не було Gemfile.lock, розгортання коду на виробництві було б основною проблемою, оскільки, як ви вже згадували, залежності та версії gem можуть змінитися.

Коротше кажучи, ви повинні бути в цілому в безпеці, використовуючи песимістичний оператор обмеження версії ( ~>), як радить rubygems.org. Тільки не забудьте повторно запустити тести після того, як зробите, bundle updateщоб переконатися, що нічого не зламалося.

Є приємна стаття Єгуди Каца, де є трохи більше інформації про Gemfile.lock.


1
Добре, тому дорогоцінні камені залишаються на встановлених версіях, записаних у Gemfile.lock. То яка мета додавання "~>"? Чим це вигідно?
Ітан

2
@ethan RubyGems має документ , який це пояснює (див. розділ "Запобігання катастрофі версій"). Суть цього полягає в тому, що він дозволяє лише збільшити останнє ціле число у номері версії (наприклад, '~> 1.0.5' дозволяє оновити до версії 1.0.9999, але ніколи до 1.1.x). Механізм дозволяє оновлювати дорогоцінні камені, але без введення несумісностей, які можуть порушити ситуацію (передбачається, що дорогоцінні камені дотримуються політики "Rational Versioning", що посилається на контури).
Abe Voelker

3
Я думаю, суть того, що ви написали, полягає в тому, що слід зберігати песимістичні обмеження версій у своєму Gemfile, щоб можна було легко оновити до останньої версії, яка відповідає як основній, так і другорядної версії. Але файл Gemfile.lock також слід використовувати і зберігати у вихідному коді, так що оновлення повинні виконуватися явно, щоб впливати на будь-яке середовище, до якого розгортається ваш код.
Кенні Евітт,

7

TL; DR

Так, використовуйте песимістичний замок ( ~>) і вкажіть семантичну версію до патчу ( Major.minor.patch) на всіх своїх дорогоцінних каменях!

Обговорення

Я здивований недостатньою ясністю щодо цього питання, навіть "експерти галузі" днями сказали мені, що Gemfile.lockіснує для підтримки версій самоцвітів. Неправильно!

Ви хочете організувати свій Gemfileспосіб таким чином, щоб ви могли бігати bundle updateбудь-коли, не ризикуючи зламати все. Щоб досягти цього:

  1. Вкажіть версію на рівні патча для всіх ваших дорогоцінних каменів з песимістичним блокуванням. Це дозволить bundle updateотримувати виправлення, але не порушувати зміни.

  2. Вкажіть refдля gems від git

Єдиним недоліком цієї установки є те, що коли виходить солодка нова мінорна / мажорна версія для дорогоцінного каміння, вам доведеться піднімати версію вручну.

Сценарій попередження

Поміркуйте, що станеться, якщо ви не заблокуєте свої дорогоцінні камені.
У вас є розблокований gem "rails"в вашому Gemfile і версії в Gemfile.lockIS 4.1.16. Ви кодуєте, і в якийсь момент ви робите a bundle update. Тепер ваша версія Rails переходить до 5.2.0(за умови, що інший камінь не заважає цьому) і все ламається.
Зробіть собі послугу і не дозволяйте цього жодному самоцвіту!

Приклад 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

Поступка
Якщо ви впевнені, що ваші тести виявлять помилки, спричинені зміною версії дорогоцінного каменя, ви можете спробувати песимістично заблоковані дорогоцінні камені на другорядній версії, а не на виправлення.
Це дозволить збільшити версію дорогоцінного каменя в межах зазначеної основної версії, але ніколи не перейти до наступної.

gem "puma", "~> 3.12"

1
це песимістичне слово тут бентежить (я розумію, це лише семантика, але все ж). якщо ви зафіксували його на версії з =, це песимістично! але ~> насправді дозволяє оновити до останньої другорядної версії.
Joel_Blum

2
Ви писали You want to organize your Gemfile in such a manner that you can run bundle update any time without risking breaking everything. Ні, це не мета. Здається, ви не можете зрозуміти різницю між bundle updateі bundle install. update оновлюєGemfile.lock і зміни версії , які ви використовуєте. Ви хочете мати можливість працювати в bundle installбудь-який час, не ризикуючи зламати все. По суті, ви змушуєте Gemfileробити те, що Gemfile.lockзадумано.
іконоборці

2
І ці «галузеві експерти» правильно: Gemfile.lock це насправді зберегти дорогоцінні версії. До (звичайно ж ) ви вирішили перезаписати з bundle update(що в принципі , як кажуть bundle overwrite_my_locked_gem_versions).
іконоборці

@iconoclast Ми тоді не погоджуємось із значенням слова "підтримувати". Для мене це передбачає обмежене відчуття змін, щоб іти в ногу з часом, а не повну незмінність.
Епіген

1
Як я бачу це (саме тому я спочатку написав відповідь), існує помилкова думка, що лише тому, що є Gemfile.lockфайл, який має всі точні версії, розробникам не потрібно вказувати версії дорогоцінних каменів Gemfile(ідея блокування "підтримує" версії). Це хибно. Розробники "підтримують" версії, вказуючи їх Gemfileта запускаючи bundle updateчас від часу.
Епіген

6

Я б точно сказав, використовуйте точні номери версій. Можливо, ви завжди можете просто заблокувати його до основної версії або ніколи не вказувати будь-яку версію, і все буде в порядку, але якщо ви дійсно хочете, щоб цей тонкодисперсний рівень контролю і мав 100% впевненість у своїй програмі під час запуску на інших машинах, використовуйте точні номери версій.

Я траплявся в ситуаціях, коли не був вказаний точний номер версії, і коли я чи хтось інший робив це bundle install, проект зламався, оскільки він перейшов на новішу версію. Це може бути особливо погано при розгортанні на виробництві.

Bundler дійсно замикає ваші специфікації дорогоцінного каменя, але якщо ви кажете йому просто використовувати основний випуск, то він блокує це. Так само знає: "О, версія заблокована на> 0,1" або що завгодно, але не "О версія заблокована спеціально на 0.1.2.3 ".


11
Якщо Gemfile.lockвін присутній, тоді Bundler насправді знає, яку конкретну версію встановити (саме тому його Gemfile.lockслід зберігати в репо Gemfile).
mipadi

3
Виконання дій bundle update <gem>може в кінцевому підсумку оновити набагато більше, ніж ви думали, навіть якщо таке Gemfile.lockє, і це може бути небезпечною та липкою ситуацією.
MrDanA

1
Я погоджуюся з рекомендацією самих RubyGems щодо цього питання: просто використовуйте песимістичне обмеження (~>). Це спонукає все співтовариство зайнятися семантичними версіями, що добре, і між цим та вбудованими функціями стабільності Gemfile.lock ваші бази повинні бути більш ніж охопленими.
user456584

1
@solidcell Я не вірю, що мені доведеться вводити джерело кожного разу, коли я оновлюю дорогоцінний камінь. Я вважаю за краще використовувати якомога точнішу версію, але, як уже згадувалося, часто можна просто використовувати обмеження ~> більшу частину часу. Однак у мене було таке, що дало мені нову, виправлену версію дорогоцінних каменів.
MrDanA

1
Вам не потрібно (і не повинно) використовувати точні версії у вашому Gemfile. Це мета Gemfile.lock. Якщо ви берете на себе Gemfile.lockконтроль над джерелом, хтось, що потягне це і зробить bundle install, отримає точно такі ж версії дорогоцінних каменів, як і ви. Встановлення точної версії Gemfileзаважає вам робити, bundle update gem_you_want_to_updateтоді як песимістичні версії ( ~>) або взагалі відсутні версії дозволяють вам запустити bundle update gem_you_want_to_updateта отримати останню (другорядну) версію
PhilT
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.