去年の失敗談から。まだ RubyGems にリリースされていない gem について、git
オプションを使って以下のような指定をした。多少改変しているけれどだいたいこんな感じ。イメージは伝わると思う。
# Use therubyracer from GitHub until cowboyd/therubyracer#413 is released. # # therubyracerにRuby 2.4対応の以下のコミットが含まれたリリースがされたらgitオプションを削除できる。 # https://github.com/cowboyd/therubyracer/commit/f5966bb55a4b0434964d66ef765907d940b4c109 gem 'therubyracer', git: 'https://github.com/cowboyd/therubyracer', ref: 'f5966bb'
Gemfile.lock の方にもこんな感じでコミットのリビジョンが記される。
GIT remote: https://github.com/cowboyd/therubyracer revision: f5966bb55a4b0434964d66ef765907d940b4c109 ref: f5966bb specs: therubyracer (0.12.2) libv8 (~> 3.16.14.15) ref
結論から言うと、GitHub リポジトリ上で rebase して force push されるとハッシュ値 (リビジョン) が変わって、開発時には存在していた対象コミットがリリース時の bundle install で取得できなくて死ぬ。後出しジャンケンで書いてみれば当たり前の話。
ちなみにこの事例で cowboyd/therubyracer リポジトリ上で rebase して force push したのは自分自身だったので気付く余地はあったわけだけど、基本的に誰がいつどう手を加えるか分からない (自分の管理にない) GitHub 上のコードは生物なので開発時に Gemfile に指定しているコミットがリリース時に存在しているとは限らない。
他にもあるかもだけど思いつくあたりでこのリスクを避ける方法は以下。
- そもそも
git
オプションを使わずにリリースされている Gem を使う git
オプションを使うなら、自分の (管理できる) リポジトリに fork して指定する- 対象の gem (コード) をリリース時の対象物に予め含めておくなど、リリース時の bundle install を不要にしておく
教訓として記しておいた。
追記
2案目について sue445 さんからいいアドバイスをもらえたので追記。
自分のリポジトリにforkした上でprotect branchしとくと完璧そう / “Gemfileでのgitオプション利用のリスク - koicの日記” https://t.co/YQTyQChN6F
— sue445 (@sue445) 2017年1月11日