👮‍♂️

Docker環境でもGitのcommitやpushの前にRubocopのチェックをする

2020/11/06に公開

Rubocop + Docker = ツライ

Ruby のプロジェクトだと Rubocop を使うのは当たり前という感じもしますよね。
VSCode では ruby-rubocop を使ったり、Vim でも dense-analysis/ale を使ったりして、コードを書きながら Rubocop のチェックを通している人も多いのではないでしょうか?

しかし最近では Docker を使って環境を構築するケースも増えていて、そうするとローカルで Rubocop を動かすことができません。
Docker のコンテナ上で実行をしてエディターに結果を表示することもできますが、やはり実行速度がローカルよりも遅いのは気になります。

とはいえわざわざエディターでのチェックのために bundle install を手元でするのは、せっかく開発環境を Docker で作っている意味が薄まってしまいます...。

ということで、エディター上でのリアルタイムでのチェックは諦めるけど、リモートに push する前に Rubocop のチェックを通すような方法を考えてみます。

Git のフック

Git には様々なイベントの前後に処理を挟むことができる Git フックという仕組みがあります。
(ドキュメント: Git - Git フック

フックできるタイミングは様々ありますが、今回はその中でも pre-commit と pre-push のフックを使って Rubocop のチェックをしてみます。
それぞれ git commit する前と git push をする前に行われる処理を追加することができます。

git commit する前に Rubocop のチェックをする

Git フックを使いたいときは次の手順で準備をします。

  1. .git/hookspre-commit というファイルを追加
  2. chmod a+x .git/hooks/pre-commit で実行権限を与える

Docker で立ち上げたコンテナ上で Rubocop を実行するために、次の内容で pre-commit を準備しましょう。

pre-commit
#!/bin/sh

if git diff --cached --name-only --diff-filter=AM | grep '\.rb$'; then
  echo '---Rubocopで警告がないかチェック---'
  git diff --cached --name-only --diff-filter=AM | grep '\.rb$' | xargs docker-compose exec -T web bundle exec rubocop --fail-level R --display-only-fail-level-offenses
fi

こうすることで git commit する前に git diff に含まれる .rb のファイルをチェックすることができます。
またチェックに引っかかったファイルがある場合はコミットを中止してくれるので、誤ってコミットすることを防げます。

git push する前に Rubocop のチェックをする

pre-commit と同様に pre-push のタイミングのフックも準備します。

  1. .git/hookspre-push というファイルを追加
  2. chmod a+x .git/hooks/pre-push で実行権限を与える

pre-push の内容は次の内容にします。

pre-push
#!/bin/sh

echo '---Rubocopで警告がないかチェック---'
docker-compose exec -T web bundle exec rubocop ./**/*.rb --fail-level R --display-only-fail-level-offenses

こうすることで git push する前にプロジェクトの全ての .rb のファイルをチェックすることができます。
またチェックに引っかかったファイルがある場合はプッシュを中止してくれるので、誤ってプッシュすることを防げます。

Rubocop + Docker + Git フック = 幸せ

Git フックを駆使することで Docker 環境でも Rubocop の手元でのチェックを自動化することができました。
GitHub Actions や CircleCI を使ってチェックしているとは思いますが、CI を待たず手元で気付くことができるとより素早く修正をすることができます。

自動でチェックをして素早く改善をして、余った時間は美味しいお菓子でも食べてのんびり過ごしましょう🍰

Discussion