iOSプロジェクトでGithubActionsを使ってdangerを回すまでのロードマップ

## はじめに
本記事はiOSプロジェクトにDangerを導入し、GithubActionsによってPRが作成された際に自動でPRのチェックやlintを走らせるための導入の記事です。

## 実行環境
* Xcode 12
* Swift 5.3
* Ruby 2.7.1
* bundler 2.1.4
* danger 8.0.5

## なぜGithubActionsなのか
dangerをCIでまわす手段はいくつかあります。(GithubActions、Sider、CircleCI, Bitrize, Jenkinsなど)
ただ新規の導入かつ会社的な制限がないのであれば、2020年10月現在はGithubActionsがベストプラクティスなような気がします。
理由は以下です。

* githubで全てが完結する。
* 即ちAPIトークンの発行とかCIサービス用のアカウント作成とか要らないのでめっちゃ楽。
* おまけに安い。Publicリポジトリはまさかの時間無制限で無料。Privateリポジトリで比較してもその他のCIサービスより安いらしい。
    * 詳しくは：[Github Actions 8ヶ月使ってみてわかったことまとめ](https://qiita.com/bigwheel/items/2ab7deb237122db2fb8d)

## 導入手順

### 1. bundlerをインストール(なければ)

```
gem install bundler
```
docker使うとかグローバルに入れるとかはご自由に。GemfileができればOK。

### 2. Gemfileを作成

```shell
bundle init
```
GemfileができたらOK

### 3. Gemfileにインストールするgemを記述

```
# frozen_string_literal: true

source "https://rubygems.org"

gem 'danger'
gem 'danger-swiftlint'

# gem "rails"
```
終わったらGemをインストール

```shell
bundle install
```
`vender/bundle`にするしないは実行する方の思想に合わせます。どっちでもOK。

### 4. dangerfileの作成

```shell
bundle exec danger init
```
色々チュートリアルが表示されるけど全部スキップ。
Dangerfileが生成されたらOK。

**注意**

* 自動生成されるので大丈夫だと思いますが、名前が`Dangerfile`以外になっていると動かないので注意。

### 5. Dangerfileの編集

好きな内容で編集。

* [APIReference](https://danger.systems/reference.html)
    * 公式。ここ見ればどんな値が使えるか分かります。
* [受託開発での iOS アプリプロジェクト新規作成プラクティス（下編：Bitrise 編）](https://qiita.com/lovee/items/811eae37928447f06b36#1-dangerfile-を追加)
    * めちゃくちゃdanger使い込んでるプロジェクトのdangerfileが載ってます。受託に限らずdangerでチェックしたいことはこちらのdangerfileを参考にすれば大抵できる気がする。

以下は僕が動作確認に使ったdangerfileの例です。

```ruby
# Check PR
warn("PRがWIPになってるよ！🐶") if github.pr_title.include? "[WIP]"

warn("PRのタイトルが短すぎるよ！🐶") if github.pr_title.length < 5

warn("PRにタイトルが書かれてないよ！🐶") if github.pr_title.length == 0

warn("PRの説明が短すぎるよ！レビュアーが見て分かる説明を書いてね！🐶") if github.pr_body.length < 5

warn("PRにassigneeが設定されてないよ！🐶") unless github.pr_json["assignee"]

pr_has_screenshot = github.pr_body =~ /https?:\/\/\S*\.(png|jpg|jpeg|gif){1}/
warn("UIレビューの時はスクリーンショットを添付してね！🐶") if !pr_has_screenshot

# 修正範囲外をチェック対象から外します。
github.dismiss_out_of_range_messages

# Swiftlint
swiftlint.config_file = '.swiftlint.yml'
swiftlint.lint_files inline_mode: true
```

**補足**　
`swiftlint.config_file = '.swiftlint.yml'`でswiftlint.ymlのディレクトリを指定しています。
プロジェクトのルートに`.swiftlint.yml`がない場合はそのディレクトリを上記で指定して下さい。

### 6. swiftlin用のymlを作成(なければ)

```shell
touch .swiftlint.yml
```
`.swiftlint.yml`の中身はお任せ。この辺参考にどうぞ。

* [SwiftLintのRules全まとめ](https://qiita.com/kagemiku/items/80e6d905dc0059c342b3)

ここまでできたら以下のコマンドを打ってみて動作確認する。

```shell
danger pr https://github.com/danger/swift/pull/95
```
動いてdangerのログがターミナルに出力されたらOK

### 7. githubAction用のymlを作成

```shell
mkdir .github/workflows
touch danger_swift.yml
```
ymlの名前は他の名前にしてもOK。
`.github/workflows`にymlがあるのが大事。

GithubのレポジトリからActionsを選んでGUI上で作ってもOK。
`Set up this workflow`を選択したら勝手に`.github/workflows`のディレクトリとymlファイルを生成してくれます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311282/1e8785b3-591c-ba71-681e-f012470dad67.png" width="500">

### 8. danger_swift.ymlの編集

以下の内容でPRの作成をトリガーにdangerを走らせることができます。

```yaml
name: Danger Swift

on: [pull_request]

jobs:
  danger:
    name: Danger
    runs-on: macos-latest
    
    steps:
      - uses: actions/checkout@master
      - name: Setup Ruby
        uses: actions/setup-ruby@v1
        with:
            ruby-version: '2.x'
      - name: cache bundle
        uses: actions/cache@v2
        with:
          path: vendor/bundle
          key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}
          restore-keys: |
            ${{ runner.os }}-gems-
      - name: setup bundle
        run: |
          gem install bundler
          bundle config path vendor/bundle
          bundle install --jobs 4 --retry 3
      - name: Run Danger
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          bundle exec danger
```

**やってること**

* Rubyのインストール
* Gemのキャッシュがあれば使用
* bundlerのインストール
* Gemのインストール
* dangerの実行
* キャッシュできたらキャッシュ(`actions/cache@v2`で勝手にやってくれる。)

**注意**

* `uses: actions/cache@v2`を間違えて`uses: actions/cache@v1`にしていたら`No such directory`みたいに表示されてキャッシュに失敗しました。

### 9. リモートリポジトリに配置

ここまでできたらプッシュします。

**注意**

* PRのbaseBranchに実行ファイルが配置されていないとPRを出してもアクションが始まりませんでした。
* baseBranchへ上記の各種実行ファイルがマージされた次のPRから動作確認ができます。

あとはPRを作成した時にgithubActionsが実行されてDangerが走るはず。
![スクリーンショット 2020-09-30 18.38.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311282/67a6c0e0-6d91-c954-8561-067a6d2203f6.png)

## 実行時間
こんな感じです。
![スクリーンショット 2020-10-04 0.48.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311282/5fc8a669-0a05-b626-16d6-b6dd773c8022.png)

## おわりに

GithubActionsでdangerをまわすまでのロードマップでした。
swiftlintはbuildPhaseでスクリプト書いとけばビルドの時に走らせたりはできるんですが、修正したかどうかはプログラマ次第なので結局レビューする時は気になっちゃったりするんですよね。
けどdangerで引っかかってるところを自動でPRにコメントしてくれるようにしておけば、レビュアーは細かいとこ気にしなくて良くなるのでレビューがずっと楽になります。
今回はCIでリントを回すだけでしたが、GithubActionsでdangerの書き込みをslackに通知したり、dangerの充実したプラグインを使ってCIを拡充したりもしたいです。

※ 僕の環境では上記のセットアップでエラーなどは出ていませんが、もし手順通りにやっても上手くいかないとかあれば是非コメントお願いします:bow:

## 参考
* [公式](https://danger.systems/reference.html)
* [github actionsでRailsをCIして結果をslackに流す(キャッシュあり)](https://qiita.com/ham0215/items/41a66a17190dd7c319a7)
* [GitHub ActionsでCacheを使ってみた](https://blog.freks.jp/github-action-cache/)
* [受託開発での iOS アプリプロジェクト新規作成プラクティス（下編：Bitrise 編）](https://qiita.com/lovee/items/811eae37928447f06b36#1-dangerfile-を追加)

## 訂正
* [7. githubAction用のymlを作成]でymlを配置するディレクトリを`.github/workflow`と記載していましたが、正しくは`.github/workflows`でした。申し訳ございません。