withオプションで特定環境でだけgemをinstallさせる

February 18, 2017

bundler には with というオプションがあります。 これは v1.10 から追加されたオプションです。 それより前から、指定グループの gem のインストールをスキップさせるために without というオプションがありました。 with はその逆で、指定のグループをインストールさせたいときに使います。

例えば、

source 'https://rubygems.org'

gem 'aws-sdk'

group :test do
  gem 'faker'
end

group :ci, optional: true do
  gem 'rugged'
end

という Gemfile を考えてみます。 ci グループには optional: true という引数がついていますが、一旦気にせずに先に進みましょう。 bundle install すると、

$ bundle install --path=vendor/bundle 
Fetching gem metadata from https://rubygems.org/............
Fetching version metadata from https://rubygems.org/.
Resolving dependencies...
Installing aws-sigv4 1.0.0
Installing jmespath 1.3.1
Installing i18n 0.8.0
Using bundler 1.14.4
Installing aws-sdk-core 2.7.11
Installing faker 1.7.3
Installing aws-sdk-resources 2.7.11
Installing aws-sdk 2.7.11
Bundle complete! 3 Gemfile dependencies, 8 gems now installed.
Bundled gems are installed into ./vendor/bundle.

となります。aws-sdk はもちろん、 test グループの faker もインストールされます。 しかし、ci グループの rugged のインストールはスキップされます。

では、次に--with ciオプションでインストールしてみましょう。

$ bundle install --path=vendor/bundle --with ci
Fetching gem metadata from https://rubygems.org/............
Fetching version metadata from https://rubygems.org/.
Using aws-sigv4 1.0.0
Using jmespath 1.3.1
Using i18n 0.8.0
Installing rugged 0.25.1.1 with native extensions
Using bundler 1.14.4
Using aws-sdk-core 2.7.11
Using faker 1.7.3
Using aws-sdk-resources 2.7.11
Using aws-sdk 2.7.11
Bundle complete! 3 Gemfile dependencies, 9 gems now installed.
Bundled gems are installed into ./vendor/bundle.

今回は、rugged もインストールされました。

つまり、optional: true のグループの gem は、with オプションの指定がある時のみインストールされます。

どこで使うか?

いろいろユースケースはあると思うのですが、私はCI環境で特定の gem をインストールするために使っています。

例にあげた rugged というのは ruby から git を使うためのライブラリです。 CIによるビルド処理の中で、git log を解析してバグが起きやすそうなファイルをPRのコメントで指摘する仕組みを運用しているのですが、その中で使われています。 つまり、rugged はCI環境でしか使われません。

rugged をインストールするには CMake が必要です。 OS X環境であれば、brew install cmake の実行が必要となります。 rugged はCI環境でしか使われないのにも関わらず、単純に Gemfile に追加すると、開発環境に一つ依存関係を追加してしまうのです。 これを避けるために、optional: true で開発環境でのインストールを回避しています。

参考までに、circleci でもし with オプションを使いたいなら、

dependencies:
  pre:
    - bundle config --local with ci

としましょう。

comments powered by Disqus