Posted at
ViibarDay 9

pull requestした差分にrubocopの結果を自動でコメントしてCircleCIをfailedにするよ

More than 3 years have passed since last update.

Viibar社員でもないのにまた登場しました @nifuramu です。おっすおっす〜〜〜

変更したファイルにrubocopやjscsを実行して pull requestに自動でコメントする

に少しだけ手を加えてCircleCIをfailedにして直すまでマージ阻止だ!!!って感じの内容です。


必要とするGem

  gem 'rubocop'

gem 'rubocop-select'
gem 'rubocop-checkstyle_formatter'
gem 'saddler'
gem 'saddler-reporter-github'
gem 'checkstyle_filter-git'


ベースとなるスクリプト

#!/bin/bash

if [ "${CIRCLE_BRANCH}" != "master" ]; then
git diff -z --name-only origin/master \
| xargs -0 bundle exec rubocop-select \
| xargs bundle exec rubocop \
--require rubocop/formatter/checkstyle_formatter \
--format RuboCop::Formatter::CheckstyleFormatter \
| bundle exec checkstyle_filter-git diff origin/master \
| bundle exec saddler report \
--require saddler/reporter/github \
--reporter Saddler::Reporter::Github::PullRequestReviewComment
fi

exit 0

こちらに手を加えて行くます。


方針

rubocopを実行した結果、何かしらエラーが発生したら exit 1 してCircleCIの結果をfailedにする。


Step1

まずはrubocopが何かしらの警告があるかどうかを調べ、その後にpull request送信、そしてfailという処理を愚直に書いてみる。

#!/bin/bash

if [ "${CIRCLE_BRANCH}" != "master" ]; then
warn=$(git diff -z --name-only origin/master \
| xargs -0 bundle exec rubocop-select \
| xargs bundle exec rubocop)

if [ -n "$warn" ]; then
echo "$warn" \
| bundle exec rubocop \
--require rubocop/formatter/checkstyle_formatter \
--format RuboCop::Formatter::CheckstyleFormatter \
| bundle exec checkstyle_filter-git diff origin/master \
| bundle exec saddler report \
--require saddler/reporter/github \
--reporter Saddler::Reporter::Github::PullRequestReviewComment
exit 1
fi
fi

exit 0

このままではhtmlやcssなどrubyに関係のない変更があった場合やそもそも何も警告がなかった場合でも $warn

1 file inspected, no offenses detected

という値となりifの中のスクリプトが実行されてしまうので、何かしらの警告があった場合のみに対応する。


Step2

Offenses: が存在すればrubocopが何かしらの警告を出しているはずなので、$warn をgrepして存在した時のみ実行するようにした。

#!/bin/bash

if [ "${CIRCLE_BRANCH}" != "master" ]; then
warn=$(git diff -z --name-only origin/master \
| xargs -0 bundle exec rubocop-select \
| xargs bundle exec rubocop)

detected=$(echo "$warn" | grep "Offenses:")
if [ -n "$detected" ]; then
# fail処理
fi
fi

exit 0


Step3

rubocop-selectで対象となるファイルが存在しない場合は bundle exec rubocop しなくてよいのでxargsコマンドに--no-run-if-emptyオプションをつけてrubocopを実行しないようにする

#!/bin/bash

if [ "${CIRCLE_BRANCH}" != "master" ]; then
warn=$(git diff -z --name-only origin/master \
| xargs -0 bundle exec rubocop-select \
| xargs --no-run-if-empty bundle exec rubocop)

detected=$(echo "$warn" | grep "Offenses:")
if [ -n "$detected" ]; then
# fail処理
fi
fi

exit 0


完成形

#!/bin/bash

if [ "${CIRCLE_BRANCH}" != "master" ]; then
warn=$(git diff -z --name-only origin/master \
| xargs -0 bundle exec rubocop-select \
| xargs --no-run-if-empty bundle exec rubocop)

detected=$(echo "$warn" | grep "Offenses:")
if [ -n "$detected" ]; then
echo "$warn" \
| bundle exec rubocop \
--require rubocop/formatter/checkstyle_formatter \
--format RuboCop::Formatter::CheckstyleFormatter \
| bundle exec checkstyle_filter-git diff origin/master \
| bundle exec saddler report \
--require saddler/reporter/github \
--reporter Saddler::Reporter::Github::PullRequestReviewComment
exit 1
fi
fi

exit 0


CircleCIで実行できるようにする


スクリプトに実行権限をつける

上記スクリプトを適当な名前で保存し、実行権限をつける。今回はrun-rubocop.shとして保存しました。

$ chmod a+x run-rubocop.sh


cicle.ymlの設定

circle.ymlに設定を追加


circle.yml

test:

post:
- run-rubocop.sh


GitHubアクセストークンを取得してCicleCIへ保存

Saddler::Reporter::Github:: PullRequestReviewComment はGitHubのアクセストークンがないと動かないのでPersonal access tokensからトークンを取得します。

取得したトークンをCircleCIのProject SettingsページのEnvironment variablesにて GITHUB_ACCESS_TOKEN という名前で保存します。

以上でpull requestした差分にrubocopの結果を自動でコメントしてCircleCIをfailedが完成です!

84ca3f43ea0ec4d7ccb315cad10cb9e1.png

なお、こちらの元ネタは @shrkw がViibar社で対応したものをちょろっといじったものとなります。手柄を横取りしたった!

あとこんな事しないでもSideCI使えばいいんじゃないかなーと思いました。