BUNDLED WITH って何?
bundler 1.10.0 以降で作成された Gemfile.lock では、BUNDLED WITH というセクションがあって、使用された bundler のバージョンがトラックされるようになっている [3485] 。
例えば bundler 1.9.0 で作成された Gemfile.lock のあるプロジェクト上で、 最新の bundler 1.10.3 を使用して bundle install --path vendor/bundle すると、 Gemfile.lock には以下の差分ができる。
+
+BUNDLED WITH
+ 1.10.3
これをもう一度 1.9.0 で bundle install すると、上の文字はきれいさっぱり消える。
BUNDLED WITH の何が困るか
多人数で開発するときには、この変更は微妙に邪魔で、意図しない Gemfile.lock 変更が出てしまうことで Gemfile.lock にコンフリクトが出たり、本番環境の bundler とのバージョン違いが顕在化してデプロイが失敗したり、あるいはローカルで bundle install したせいで git pull ができなかったりしそうに見える。まあ git checkout -- Gemfile.lock すればいいけど、逐一やらねばならなくなってめんどくさい。
で、この変更が原因で、本家の issue がプチ炎上することになってしまったのだけど、その本家の issue を見ると今回の変更の意味がよくわかった。
本家が伝えたかったこと
- まず、
bundler開発者としては、ユーザがどのバージョンでbundle installしたのかという情報は、大昔からトラックしたかったものだった。今回、多大な努力のうえでようやく実装することができた - 本家としては、以下のようなユースケースのフローを想定している
-
bundle installすると、Gemfile.lock内のBUNDLED WITHを更新する(ただし、より新しい場合のみ) - 更新したら、他の
gemをアップデートした場合とまったく同じように、Gemfile.lockの更新をコミットする -
BUNDLED WITHよりも古いバージョンのbundlerを使っている人は、BUNDLED WITHの記述を更新しない。が、bundlerを更新するように注意書きが出る
-
- …というフローを想定していたが、現在は移行期のため以下のような問題が出ている
-
1.9.9以前のbundlerではGemfile.lock内のBUNDLED WITHを削除してしまう - だから
1.9.9以前の人と1.10.0以後の人とでgitのやり取りをしていると、しょっちゅうファイルの変更が衝突してしまう - この問題は、全員が
1.10.0以降になれば起こらなくなる
-
- 今回の変更はワークフローにこそ影響はあるかもしれないものの、
bundlerそれ自体としては互換性を失う変更をしていないし、SemVerにも反していない - bundler開発者はめっちゃ頑張って開発者のためになるよう作り込んでるわけで、今回それで迷惑かけちゃってごめんね?
-
1.9系のアップデートは出さない。出したところで1.10.X以降にアップグレードしたほうが根本的解決になるから、1.9系を利用し続ける意味はない - これでもなお問題となるものがあるようであれば、きちんとした形で教えてほしい
おこでした。
あ、ちなみに、『BUNDLED WITH で指定されたバージョンの bundler を起動する』機能は実装される可能性があるらしい。できたらめっちゃ素敵。
@suu_g の推奨対応
bundle install に --frozen オプションをつけよう。役に立つわりに長年ほとんど注目されることもなかった不遇のオプション1だが、ここに来てようやく報われるときが来たようだ。レリゴーだ。
bundle install に --frozen オプションをつけると、その手元では Gemfile.lock を変更することはなくなる。このオプションは .bundle/config に保存されるので最初の一回だけ指定すればいい。
凍結されたディレクトリでは、Gemfile.lock に変更は行われないし、行われるような変更を許容しなくなるので、確実に Gemfile.lock を適用したいというとき(デプロイ時)には非常に便利。
この状態で Gemfile を変更しようとすると、「フリーズさせているので Gemfile.lock が更新できません」と言ってくるようになる。開発環境では Gemfile を変更したときには凍結を解除しなければならない、のだけど、その手段はちゃんと準備されていないのでちょっと不便。
You are trying to install in deployment mode after changing
your Gemfile. Run `bundle install` elsewhere and add the
updated Gemfile.lock to version control.
If this is a development machine, remove the Gemfile freeze
by running `bundle install --no-deployment`.
上は Gemfile に変更を加えて bundle install を試したときの公式のメッセージ。 bundle install --no-deployment でいいと書いているが、これは大嘘。素直に従ってこれを実行すると、以前に設定してあった BUNDLE_PATH などのオプションをガン無視して system ruby 上に gem を install してしまう。危険。
だからこの場合は、.bundle/config に書かれた設定を手動で削除するのがベストな方法だ。
---
BUNDLE_BIN: ".bundle/bin"
BUNDLE_FROZEN: '1' ## この行を消す
BUNDLE_PATH: ".bundle/gems"
BUNDLE_DISABLE_SHARED_GEMS: '1'
コマンドで設定を削除することもできる。こっちの方が簡単か。
$ bundle config --delete frozen
それと、 bundler のバージョンを可能な限り 1.10 以降に上げよう。現在問題が起きているのは 1.9 以前と 1.10 とが混在しているからなので、それをすべて上げてしまえば問題は起こらなくなる。
1.10 で追加された BUNDLED WITH だけど、これは 1.9 以前を通すと消えてしまう。それで編集コンフリクトが多発し、問題が大きく見えていたってだけのことだった。…というのは先述の通り。
さて、それでは開発者や本番環境に対して適用するべき具体的なものは何か、以下で説明していく。
各開発者のするべき対応
-
bundle install時にはとにかくgem updateをする - 他の人のアップデートを見たら自分もアップデートする
-
Gemfile.lockのBUNDLED WITH行でコンフリクトしたらgit checkout -- Gemfile.lock; gem update bundlerする -
Gemfile.lockのコミットには気を使う。git add .とかせず、コミット単位を分けておく -
Gemfile.lockは、内容をアップデートする意思のあるとき以外は極力変更しない。変更する気のないときは、手元環境でもbundle installに--frozenオプションをつけておく -
frozenさせたGemfile.lockを変更するときは手動。.bundle/config内にあるBUNDLE_FROZENの行を削除する
みんながこれやれば平和な開発チームになる。
本番環境でとるべき対応
-
bundle installに--frozenオプションを追加する
これに限る。無駄な更新をデプロイ先で行わせないこと、大事。
bundler のオプション一覧を見ると --deployment も気になるかもしれない。これは --frozen と --path とを組み合わせたオプションで、つまり以下のような挙動をしている:
-
vendor/bundle以下に gem をインストールする(--path=vendor/bundle) -
Gemfile.lockを変更しないようになる(--frozen)
初回ならこれを使っていくので問題ないが、 --path 指定を上書きされてしまう点には注意が必要。2
個人的な感想
BUNDLED WITHに書かれたバージョンは増えこそすれ巻き戻ることはない仕様だそうなので、世の中の bundler がすべて 1.10.0 以降になれば状況はまた変わるでしょう。いまは狭間のタイミングだから混乱が起きているわけで。
それに、デプロイ先に --frozen を使うようにすれば、現状これはほとんど問題にならなくなる。みんな手元の bundler をアップデートしたうえでデプロイ先では --frozen しよう。Gemfile.lock should never bother you anymore.
あとソフトウェア製作者への応援大事だし、自分の期待通りに動かなくなったからといってOSS作者に不満や修正要求をぶつけちゃダメ。自分で直してプルリク作ろう。まじ本家issue読んでると作者たちかわいそうになる。
そんな感じ。誰か私も応援してください。わぁいストック。
著者紹介
@suu_g。バンドラーの記事をたまに書く人。まれに無線とかする。