[Ruby] bundler 2 へのアップグレード方法

軽い気持ちでbundlerを2系にアップデートしたらいろいろはまったので記事を書きました。

bundler 2の変更点

詳しくはこちらのアナウンスにありますが、主な目的はメンテナンスが終了されたRubyやRubyGemsのバージョンのサポートを終了することのようです。また今後はRubyのライフサイクルと同じ1年サイクルで、bundler 2がサポートするRubyのバージョンも修正されるようです。また、1つのRubyのバージョンで、複数のbundlerのバージョンを切り替えて使用できるBundler Trampoliningという機能が追加されています。

bundler 2へのアップグレード方法

詳しくはこちらのアップグレード方法にあります。かいつまんで説明すると以下のようになります。

  1. Rubyのバージョンが2.3.0以上であることを確認します。
  2. RubyGemsのバージョンが2.5.0以上であることを確認します。2.5.0より低い場合は gem update --system でバージョンをあげます。この時、同時に最新のバージョンの bundler がインストールされます。
  3. (オプション) 特定のバージョンの bundler をインストールする場合は、次のコマンド gem install bundler -v 'バージョン' でインストールします。既に bundler がインストールされている場合でも、Bundler Trampoliningにより共存が可能なのでそのままインストールできます。アンインストールする場合は gem uninstall bundler -v 'バージョン' で削除します。
  4. (オプション) 既存のプロジェクトで1系が利用されている( Gemfile.lock ファイルの BUNDLED WITH の値が 1.x.x である )場合は、次のコマンド bundle update --bundler で2系に更新されます。

CI環境(CircleCI)をbundler 2にアップグレードする

同じ手順でCI環境も対応できるだろうと思ったらできませんでした。結論から言うとCircleCIのexecutorとして利用していたコンテナイメージ circleci/ruby:2.5.1-node参照)に環境変数 ENV BUNDLER_VERSION=1.16.6 が設定されていたためでした。 BUNDLER_VERSION は、bundler が実行時に利用するバージョンを決定する際に参照する環境変数で、通常は Gemfile.lock ファイルの BUNDLED WITH の値を参照しますが、この環境変数が設定されている場合はそれを無視して BUNDLER_VERSION の値を参照します。(これは、 Gemfile.lock ファイルがない場合に bundler のバージョンを指定するために使用する値です。)この環境変数のメジャーバージョンと、Gemfile.lock ファイルのメジャーバージョンが一致しない場合、 bundle install はエラーとなります。

よって正しい対応方法は、 BUNDLER_VERSION の値を2系に上書きし、 gem update --system を実行する、でした。

executors:
  ...
     docker:
       - image: circleci/ruby:2.5.1-node
         environment:
+          BUNDLER_VERSION: 2.1.4

jobs:
  ...
    steps:
      ...
-      - run: bundle install --path vendor/bundle
+      - run:
+          name: bundle install
+          command: |
+            sudo gem update --system
+            bundle config set path 'vender/bundle'
+            bundle install

あと bundle install コマンドの --path オプションが非推奨になったようで、あわせて更新しました。( bundle install --path vendor/bundle って何も考えず呪文のように打ち込んでた頃が懐かしいです。)

おまけ

近頃、RubyGemsとbundlerのリポジトリが統合されたというアナウンスがありました。リポジトリだけでなくチームも統合されたということで、今後ますます安定したメンテナンスが行われていくことが期待されます。このようなコミュニティ活動を支えているのが Ruby Together という団体(?)で、ここで集められた資金がコミュニティに還元され、メンテナンス等に生かされているようです。Rubyコミュニティに貢献する方法の1つとして、より多くの人の目に止まればいいなと思いました。