こんにちは、レシピ事業部バックエンド基盤部の石川です。これは RuboCop のバージョンを上げましょうという記事です。
なんだか最近 RuboCop を使っていたら .rubocop-29343e612b03ba2227a3c3390a755e8d.ymlのような名前のファイルが .gitignore を貫通してきませんか?
これは他リポジトリなどのリモートにある設定ファイルを inherit_fromで参照したときに作られるキャッシュファイルです。ちょっと前までは .rubocop-https---raw-githubusercontent-com-cookpad-styleguide-master--rubocop-ymlのような名前だったのが、2025 年末あたりに .rubocop-remote-23b9c67aff31e0f9d6c4a89d5eb660cb.ymlのような名前になり *1、そのあと現在の名前になりました *2。現在の名前は $original_name-$hash.ymlという規則になっています。
そのような感じでキャッシュファイルの名前が変わり、そしてよくある .gitignore では .rubocop-https?--*のみが ignore されていることが多く、新しいファイル名がこのルールに引っかからなくなったため git diff に現れるようになったという次第です。
さて、実は先日リリースされた RuboCop v1.84.2 からは、デフォルトでこれらのキャッシュファイルがプロジェクトの一番上のディレクトリではなく ~/.cache/rubocop_cache/のような共通のディレクトリへ保存されるようになりました *3。
したがって、お使いの RuboCop のバージョンを上げていただければこれらのキャッシュファイルは git diff を邪魔しなくなります。プロジェクトのディレクトリの外に保存されるためです。お試しください。
Include/Exclude に関する注意点
ところで、この変更に伴い、inherit_fromで参照される設定ファイルの側で Includeや Excludeを設定している方には注意点があります。Includeや Excludeでは相対パスを使って RuboCop の対象となるファイルを制御できますが、実はこの相対パスの起点が設定ファイルの名前によって変わります。
https://docs.rubocop.org/rubocop/configuration.html#path-relativity
In
.rubocop.ymland any other configuration file beginning with.rubocop, files, and directories are specified relative to the directory where the configuration file is. In configuration files that don’t begin with.rubocop, e.g.our_company_defaults.yml, paths are relative to the directory whererubocopis run.
上記のドキュメントに書かれているように、名前が .rubocopから始まる設定ファイルではその設定ファイルの場所からの相対パスになり、それ以外の場合は rubocopコマンドが実行された場所からの相対パスになります。
今のところ、これは inherit_fromで参照されている先の設定ファイルの名前についても同様に判断される挙動になっています。したがって RuboCop のバージョンを上げると意図しない挙動になる可能性があります。
RuboCop v1.84 では、元の設定ファイル名の先頭がキャッシュファイル名の先頭に残る上、キャッシュファイルの保存先がプロジェクトの一番上ではなくなります。このためリモートにある .rubocop.ymlを inherit_fromで参照している場合、Includeや Excludeの相対パスの起点がプロジェクトの一番上でなくなってしまいます。
実際にファイル名によって挙動が変わる様子を以下に示します。ふたつ実行していて、最初はピリオドありの .rubocop.yml、次はピリオドなしの rubocop.ymlを使っており、両方とも中身は Excludeです。両者について RuboCop v1.84.2 を動かすと、前者は spec/app_spec.rbが除外されず検査対象に残ってしまっています。なお RuboCop v1.84.1 のデフォルト挙動では前者でも後者と同じく spec/app_spec.rbが対象になっていませんでした。
% rubocop -v
1.84.2
% tree -a .
.
├── .rubocop.yml
├── app.rb
└── spec
└── app_spec.rb
2 directories, 3 files
% cat .rubocop.yml
inherit_from: https://gist.githubusercontent.com/nekketsuuu/a0081c4738b52e7fb25e28201a0e6947/raw/977ff9c55aa0b801a023600241a2d7b18ac003ca/.rubocop.yml
# inherit_from: https://gist.githubusercontent.com/nekketsuuu/a0081c4738b52e7fb25e28201a0e6947/raw/977ff9c55aa0b801a023600241a2d7b18ac003ca/rubocop.yml
AllCops:
DisabledByDefault: true
% curl -fsSL https://gist.githubusercontent.com/nekketsuuu/a0081c4738b52e7fb25e28201a0e6947/raw/977ff9c55aa0b801a023600241a2d7b18ac003ca/.rubocop.yml
AllCops:
Exclude:
- 'spec/**/*'
% rubocop --list-target-files
app.rb
spec/app_spec.rb
% nano .rubocop.yml
% cat .rubocop.yml
# inherit_from: https://gist.githubusercontent.com/nekketsuuu/a0081c4738b52e7fb25e28201a0e6947/raw/977ff9c55aa0b801a023600241a2d7b18ac003ca/.rubocop.yml
inherit_from: https://gist.githubusercontent.com/nekketsuuu/a0081c4738b52e7fb25e28201a0e6947/raw/977ff9c55aa0b801a023600241a2d7b18ac003ca/rubocop.yml
AllCops:
DisabledByDefault: true
% rubocop --list-target-files
app.rbこれを避けるため、inherit_fromしている先のファイル名が適切かチェックしておくのが良いでしょう。弊社では mv .rubocop.yml rubocop.ymlとしたあと、互換性のために .rubocop.ymlでは inherit_from: rubocop.ymlで参照しておいて徐々に移行していくという手順を試しています。
以上、最近の RuboCop についての情報共有でした。まずはぜひバージョンを上げてみてください。