1. nifuramu

    Posted

    nifuramu
Changes in title
+pull requestした差分にrubocopの結果を自動でコメントしてCircleCIをfailedにするよ
Changes in tags
Changes in body
Source | HTML | Preview
@@ -0,0 +1,182 @@
+
+Viibar社員でもないのにまた登場しました @nifuramu です。おっすおっす〜〜〜
+
+[変更したファイルにrubocopやjscsを実行して pull requestに自動でコメントする](http://packsaddle.org/articles/saddler-overview/)
+
+に少しだけ手を加えて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という処理を愚直に書いてみる。
+
+```bash
+#!/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して存在した時のみ実行するようにした。
+
+```bash
+#!/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を実行しないようにする
+
+
+```bash
+#!/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
+```
+
+# 完成形
+
+```bash
+#!/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](https://github.com/settings/tokens)からトークンを取得します。
+
+取得したトークンをCircleCIのProject SettingsページのEnvironment variablesにて `GITHUB_ACCESS_TOKEN` という名前で保存します。
+
+以上でpull requestした差分にrubocopの結果を自動でコメントしてCircleCIをfailedが完成です!
+
+![84ca3f43ea0ec4d7ccb315cad10cb9e1.png](https://qiita-image-store.s3.amazonaws.com/0/978/d94c0010-a201-e3fd-4dd6-0a9756496324.png "84ca3f43ea0ec4d7ccb315cad10cb9e1.png")
+
+
+
+
+なお、こちらの元ネタは @shrkw がViibar社で対応したものをちょろっといじったものとなります。手柄を横取りしたった!
+
+あとこんな事しないでも[SideCI](https://www.sideci.com/)使えばいいんじゃないかなーと思いました。