TL;DR
GitHub Actions で RuboCop を実行する際,デフォルトでは Gemfile に記載されている gem を余剰にインストールする必要があり冗長性が生じる.そこでBundlerのグループ機能を使って最小限の gem をインストールし,ジョブの最適化を行う.
具体的な手順は次のとおりである,RuboCopの関連gemを:rubocopグループに入れる.bundle configコマンドを使用して,withとwithoutを設定することで,:defaultグループに属するgemを除いて:rubocopグループのgemのみをインストールすることができる.GitHub Actionsでは,ruby/setup-ruby@v1アクションを使用してRubyを設定し,bundler-cacheフィールドの値をfalseに設定する.
以上の手順により,bundle installの所要時間が20秒程度に短縮された.
諸言
CI ツール (GitHub Actions,Circle CI など) で Rubocop を実行する場合,実行環境 (Ubunbu など) に Rubocop gem 群をインストールする必要がある.ただし,デフォルトでは Gemfile に記載された gem (または,RAILS_ENVなどの環境変数に指定された test などのグループに属する gem) がインストールされ,冗長性が生じる.本稿では,Bundler のグループ機能によってインストールする gem を最小化し,CI ジョブの実行最適化を図る.
Gemfile
本稿では,rubocop のほかに,rubocop-{capybara, factory_bot, performance, rails, rspec} gem をバンドルしている.これらの gem 群を rubocop グループに入れる.
- group :development, :test do
+ group :development, :test, :rubocop do
gem "rubocop", require: false
gem "rubocop-capybara", require: false
gem "rubocop-factory_bot", require: false
gem "rubocop-performance", require: false
gem "rubocop-rails", require: false
gem "rubocop-rspec", require: false
end
Bundler のドキュメントによれば,明示的にグループに属していない gem は, :default グループに属している.
# These gems are in the :default group gem 'nokogiri' gem 'sinatra'
したがって,:rubocop グループの gem 群のみをインストールするには,:default グループに属す gem 群を除き,:rubocop グループの gem 群のみをインストールするよう指定すればよい.
指定する方法には,次の2つがある.
1
編集後に気づいたが,この方法のほうが良い.
BUNDLE_WITHと BUNDLE_WITHOUT を指定する
次のように,環境変数 BUNDLE_WITH の値に rubocop を, BUNDLE_WITHOUT の値に default を設定すれば,:default グループに属す gem 群を除き,:rubocop 群のみをインストールすることができる.
rubocop ジョブは次のようになる.
# (省略)
jobs:
rubocop:
runs-on: ubuntu-latest
env:
BUNDLE_WITHOUT: "default development test production"
BUNDLE_WITH: rubocop
steps:
- uses: actions/checkout@v3
- uses: ruby/setup-ruby@v1
- name: Install dependencies
run: bundle install --jobs 4 --retry 3
- name: Run rubocop
run: bundle exec rubocop
2
bundle config で with と without を指定する
次のように,bundle config の with の値に rubocop を, without の値に default を設定すれば,:default グループに属す gem 群を除き,:rubocop 群のみをインストールすることができる.local オプションは,設定がローカルに行われるよう指示する.
bundle config set --local without default
bundle config set --local with rubocop
ruby/setup-ruby@v1 の bundler-cache を偽に設定する
GitHub Actions で Ruby を利用可能するためのアクション ruby/setup-ruby@v1 を用いることにする.
デフォルトでは,ruby/setup-ruby@v1 は Gemfile 及び Gemfile.lock を参照して
:default を除かずに bundle install してしまうため,bundler-cache フィールドの値を false に設定する必要がある. (bundle コマンドは,ruby/setup-ruby@v1 を実行したのちに利用可能になる.)
- uses: ruby/setup-ruby@v1
with:
bundler-cache: false
rubocop ジョブ
以上から,rubocop ジョブは次のようになる.
# (省略)
jobs:
rubocop:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: ruby/setup-ruby@v1
with:
bundler-cache: false
- name: Set up Ruby
run: |
bundle config set --local without "default development test production"
bundle config set --local with rubocop
- name: Install dependencies
run: bundle install --jobs 4 --retry 3
- name: Run rubocop
run: bundle exec rubocop
結語
これによって,1分以上掛かっていた bundle install が 20秒ほどに短縮された.