TL;DR
2017-07-20 から、bundle gem my-awesome-gem
の生成物で、Gemfile.lockをgit ignoreしなくなった。
Stop gitignoring Gemfile.lock in default template #5822
なんでgit ignoreしていたのか、なぜするべきなのか、どうしてしなくなったのか、あたりを整理する。
なおわたしはignoreしているほうがいいとおもってる。
きっかけ
わたしがこう反応したら、
そりゃgemの開発者は無いと困るけどさ 利用者のが圧倒的に多いじゃん
理解できねー
こういう反応を複数もらったので。
あれ、利用者がgemfile.lockあってなんか困ります?
直接それが原因では困らないが、実質困るケースが増えると思う。
環境
$ ruby -v ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-linux] $ bundle --version Bundler version 1.16.2 $ bundle gem test-pack (snip) $ cat .gitignore /.bundle/ /.yardoc /_yardoc/ /coverage/ /doc/ /pkg/ /spec/reports/ /tmp/
定説的なやつ
たとえばrailsアプリなど、アプリケーションはGemfile.lockをコミットすべき。
gemはGemfile.lockをコミットしないべき。
どっかできいたことあるはず。んで、よく引き合いに出されるのがClarifying the Roles of the .gemspec and Gemfile。
日本語訳はgemspecとGemfileの役割をはっきりさせておく。
許可取ってるか取ってないかわからない(許可取ってたらごめんね)翻訳ですが、これを勝手に許可無く掘り起こしてる人がいる。
今読み返すと、それコミットしてもいいでしょ、って言えるぐらいだなー。なので掘り下げる。
gem installやbundle installでrubygems.org 及びそのクローンの場合
metadataをみてるはず(要出典)。
metadataってなんだよ
$ bundle exec rake build
test-pack-0.1.0.gemができる
中身は
checksums.yaml.gz
data.tar.gz
metadata.gz
metadataの中身はこう。
--- !ruby/object:Gem::Specification name: test-pack version: !ruby/object:Gem::Version version: 0.1.0 platform: ruby authors: - Sanemat autorequire: bindir: exe cert_chain: [] date: 2018-07-22 00:00:00.000000000 Z dependencies: - !ruby/object:Gem::Dependency name: bundler requirement: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' - !ruby/object:Gem::Dependency name: rake requirement: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' description: fix me email: - o.gata.ken@gmail.com executables: [] extensions: [] extra_rdoc_files: [] files: - ".gitignore" - CODE_OF_CONDUCT.md - Gemfile - Gemfile.lock - LICENSE.txt - README.md - Rakefile - bin/console - bin/setup - lib/test/pack.rb - lib/test/pack/version.rb - test-pack.gemspec homepage: http://example.com licenses: - MIT metadata: allowed_push_host: 'TODO: Set to ''http://mygemserver.com''' post_install_message: rdoc_options: [] require_paths: - lib required_ruby_version: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' required_rubygems_version: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' requirements: [] rubyforge_project: rubygems_version: 2.7.6 signing_key: specification_version: 4 summary: fix me test_files: []
rubyとかgit ls-filesとかもう残ってない。
そして、bundle exec rake build
の場合、my-awsome-gem.gemspec
の中身だけ反映されている。
Gemfileにだけ書いたものはmetadataに入ってない。
与太話: Gemfile 消したら bundle exec rake build 動かなかった :thinking:
Gemfile, Gemfile.lock
これがbundlerの独自ファイルなのは、忘れてるけど言われりゃそうだろうなと思う。
my-awsome-gem.gemspec
これはbundlerの独自ファイルだっけ? 実態として作らなきゃいけないかは定かではない。
たとえばいまはseattlerbぐらいでしか使われていないhoeの場合、gemspecファイルがリポジトリにないが、動的に作っているのか、何だったか忘れた(要出典)
使用例: https://github.com/seattlerb/ruby_parser
つまり
metadataに反映されるかされないかだけで、どうでもいい、とも言える
bundle installでgit repositoryをsourceにする場合
リポジトリのGemfileを見に行くんじゃない? (要出典)
このときlockみてるのかなあ 見てないんじゃないの(要出典)
gem install, bundle installのしくみ
このmetadataをかき集めて、それを満たす最大のバージョンをインストールする。(要出典)
前半ここまで。
Gemfile.lock
アプリケーションを作っている時に、Gemfile.lockなかったら、バージョン固定できなくてつらい。
これは説明いいよね。
gemとGemfile.lock
ここは思想の違い。
lockがあれば、CIで固定のバージョンで通ったことを確認できる。
この組み合わせだと動くよ、ってテストの範囲では言うことができる。
ただ、それってなんの意味があるの、利用者の手元でgem install, bundle installするときに、
なんの関係もないじゃん、って思ってしまう。利用者ではmetadata見るだけなので。
lockがない場合、たとえば新しいcontributorがバグフィックスしたり、新しいフィーチャー持ってくるときに、pull requestを送ったら依存でぶっ壊れてテストが真っ赤というのがよくある。
Over time, however, it became clear that this practice forces the pain of broken dependencies onto new contributors, while leaving existing contributors potentially unaware of the problem.
https://github.com/bundler/bundler/issues/5879#issue-244213907
大体の場合、new contributorsは、自分のfixやfeature入れる前に、もうぶっ壊れてることを報告して、何なら自分で直したりして、test greenにしてから、自分の変更を入れる必要がある。
new contributorsはテンション下がるよね。
まあそれはそうなんだけど、それはもうぶっ壊れてるんだよね。
つまりGemfile.lockをコミットすることで、最新バージョンで動かす責任をnew contributorsからほかのcomittersに移したと言える。
新しい人が開発しやすくなってよかったね。gemとしてリリースするものが動くかどうかはcommiterの責任ですよ。
めでたしめでたし。
なわけないじゃん。。利用者がinstallしようとするときの組み合わせではない古いlockの組み合わせで確認オッケーリリースって事故しか見えない。
そんな事故起こりうるの?って疑問には、だってそれがpainだからゆうてるやん、ってことで。
じゃあどうやって保証するのというと、保証なんてできないので、lockをignoreしておいて、定期的にciを動かしてfailしたら直し続けるしかない。
lockありのテストとlock消してbundle/gem install してテスト、の両方やるでもいいよ。
同じ話の言い換えで、ぶっ壊れてることに気づきづらくなるというのもある。Gemfile.lockを消したpull requestを定期的に送るのかな。
利用者が困る
そりゃgemの開発者は無いと困るけどさ 利用者のが圧倒的に多いじゃん
理解できねー
ぶっ壊れgemがよりリリースされやすくなって利用者が困るの説明でした。