Danger⚡️をBitriseCIで導入してGithubのコードレビューを自動化する方法

Danger使ってますか？

最近、Android/iOSアプリの勉強会でちょくちょく耳にするようになったDanger⚡️

今回はDangerをBitriseで簡単に導入する方法から、
どんなことができるのかについてまとめて行きます。

# WHAT IS DANGER⚡️ ?
まずはDangerについて説明します。
[公式サイト](http://danger.systems/ruby/)を読んで頂ければ大体わかるので詳細は公式サイトをみて下さい。
ざっくり言うとGithub上で行うPull RequestやMerge RequestをCI上で解析して自動でコメントしてくれるツールです。

例えば、

- 1000行を超えるプルリクエストが投げられた
- マイルストーンが設定されていない
- スクリーンショット貼ってない
- WIPが付いている
- TODOが残っている
- テストコードが書かれていない
- などなど

なので、プロジェクト開始前にチームで決めたプルリク時のルールなどをコードで運用でき、
プルリクの最初のレビュアーをbotに任せて自動化することができます。

# Dangerのセットアップ
まずは、Gitで管理するAndroid/iOSアプリのプロジェクトルートで
以下のコマンドを実行します。

```console:
$ bundle init
```

すると、Gemfileが生成されたと思いますので
こちらのファイルに```gem "danger"```と記述して下さい。

```rb:Gemfile
# frozen_string_literal: true
source "https://rubygems.org"

git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }

# gem "rails"
gem "danger" // ←ココに追加！
```

記述後は下記コマンドを実行しましょう！

```console:
$ bundle install
$ bundle exec danger init
```

すると、コンソール上にDangerの導入チュートリアルが表示されますが、
Enterを押してどんどん飛ばして下さい⚡️

ここまでの操作でカレントディレクトリにDangerfileというファイルが追加されたと思います。

```console:
$ ls
Dangerfile   Gemfile    Gemfile.lock ...
```

生成されたDangerfileには先ほどのDangerの初期化処理で簡単なサンプルコードが記述されています。
こちらのコードはrubyで記述されています。

# Github Access Tokenの生成
続いて、CIからGithubにアクセスする為のAccess Tokenを取得します。
取得するには以下のページにアクセスし、右上のGenerate new tokenからトークンを新たに取得します。

https://github.com/settings/tokens
![GithubAccessToken.png](https://qiita-image-store.s3.amazonaws.com/0/126555/f68671ce-1d56-2a57-ab37-90191da92e55.png)

適切な権限が付与されたAccess Tokenが取得できたら
Github側の設定は完了です。

# Bitriseの設定
続いて、Dangerfileをもとにプルリクを解析するCI側の設定です。
DangerはありとあらゆるCIにサポートしていますが、今回はBitriseを設定方法をまとめます。

まずは、BitriseにGithubでソース管理しているAndroid/iOSアプリのリポジトリを登録します。

登録後、Workflowの環境変数設定のタブで```DANGER_GITHUB_API_TOKEN```という名前で
先ほどGithubで生成したAccess Tokenを環境変数に登録して下さい。

![access_token.png](https://qiita-image-store.s3.amazonaws.com/0/126555/39375520-092d-7b6c-1251-efcf35d34535.png)

Access Tokenの設定が終わったら、CI上でDangerをインストール、実行するスクリプトを記述します。

```script:
bundle install
bundle exec danger
```
ここまでで、CI上での設定は終了です。





# コメント出力
ここまでで、Dangerの基本的な設定は終わりました。
続いて、Dangerfileを修正してプルリクのコメント書式を色々試してみます。

```ruby:Dangerfile
# メッセージをプルリクのコメントに表示
message "Hello Danger!"

# ワーイングをプルリクのコメントに表示
warn "Danger Warning!!"

# プルリクをエラー表示でブロックする
fail "close PR"

# マークダウンも使える
markdown("# markdown")
markdown("## markdown")
markdown("### markdown")
```

上記のようにDangerfileを編集して、適当にプルリクをしてみると
Botアカウントがコメントしてくれます。

![comment.png](https://qiita-image-store.s3.amazonaws.com/0/126555/6a58a57d-1091-d1d8-64bd-5e9ebd84d734.png)
failでPRを落としてくれたりもします。

# Try! Danger⚡️
さて、Dangerの設定とコメントへの出力方法は学んだので
あとはDangerfileを編集して実現したいことをコードで書くだけ

```ruby:Dangerfile
# プルリクが編集中
warn("このプルリクが編集中のようです。") if github.pr_title.include? "[WIP]"

# プルリクがでかすぎる
warn("プルリクの変更箇所が多すぎるので分割しましょう。") if git.lines_of_code > 500

# マージコミットがある
has_merge_commit = git.commits.any? { |c| c.message =~ /^Merge branch '#{github.branch_for_base}'/ }
fail "マージコミットがあるのでリベースしましょう。" unless has_merge_commit

# マイルストーンが設定されていない
has_milestone = github.pr_json["milestone"] != nil
warn("プルリクにマイルストーンが設定されていないようです。", sticky: false) unless has_milestone

# 誰もアサインされていない
has_assignee = github.pr_json["assignee"] != nil
warn("誰もアサインされていないようです。", sticky: false) unless has_assignee
```

試しに

- 作業ブランチの改変が500行を超える
- タイトルに[WIP]がついてる
- ブランチをきってからベースにコミットがある
- マイルストーンが設定されていない
- 誰もプルリクにアサインされていない

このようなプルリクを投げてみました。
すると、Botアカウントがちゃんとプルリクの1stレビュアーとしてコメントしてくれました。

![output.png](https://qiita-image-store.s3.amazonaws.com/0/126555/9d577fec-010c-c43e-68be-35c70f01bd78.png)

# まとめ
今回、Dangerの基本的な使い方をまとめました。
Android-lintのDangerプラグインとか使うとコードの中もチェックして
色々できるようなので今後もDanger活用してみたいです。