CircleCIとDangerでPull Requestの自動チェックをやってみた

これはなに

Dangerとは

github.com

  • DangerはPull Requestの状態をチェックするツール
  • マイルストーンアサインが未設定のとき、マージ先が特定のブランチに向いてないとき、コメントで警告したりPRを失敗させたりできる

Dangerのインストール

  • DangerはRuby製でGemからインストールできる
  • Dangerには複数のプラグインがあり、今回はSwiftLintをDangerで実行させる danger-swiftlint を導入した
gem "fastlane", "2.94.0"
gem "danger", "5.5.13"
gem "danger-swiftlint", "0.16.0"

Dangerの初期化

  • bundle exec danger init するとDangerfileができる
  • DangerfileにはPull Requestでチェックして欲しい状態や条件を記述する
  • 俺はブランチのチェックは警告にしたが、失敗にすると安心で安全な開発環境をつくれると思う
# RPの差分範囲外に対する指摘はすべて無視
github.dismiss_out_of_range_messages

# --------------------
# swiftlint
# --------------------
swiftlint.config_file = '.swiftlint.yml'
swiftlint.lint_files inline_mode: true

# --------------------
# pr title
# --------------------
warn('このPRは作業中です') if github.pr_title.include?("WIP") || github.pr_title.include?("wip")

# --------------------
# base branch
# --------------------
is_to_master = github.branch_for_base == 'master'
is_to_release = github.branch_for_base.include?("release")
is_from_release = github.branch_for_head.include?("release")
is_from_development = github.branch_for_head.include?("dev") || github.branch_for_head.include?("development")

warn('master へマージできるのは release branch のみ(緊急時はOK)') if is_to_master && !is_from_release
warn('release へマージできるのは dev branch のみ(緊急時はOK)') if is_to_release && !is_from_development

# --------------------
# milestone
# --------------------
warn('このPRにマイルストーンを設定してください') if github.pr_json["milestone"].nil?

# --------------------
# assignee
# --------------------
warn('このPRにアサインしてください') if github.pr_json["assignee"].nil?

Dangerの実行

  • 実行方法は色々あるが、今回はfastlaneから実行させた
  • 個人的にツールの実行や環境変数など可能な限りFastfileに記述して、CIはfastlaneの実行とmacOSのセットアップに留めたい派です
danger(
  danger_id: "unit-tests",
  dangerfile: "tests/MyOtherDangerFile",
  github_api_token: ENV["GITHUB_API_TOKEN"],
  verbose: true
)

https://docs.fastlane.tools/actions/danger/#danger

Dangerを導入した目的

  • 目的は新メンバーへのオリエンテーションを少しでも良い感じにすることだった
  • オリエンテーションを「あーでこーで」みたいなレクチャー形式にするのではなく、開発中に気がつける仕組みにしたかった
  • コーディングしてコミットしてPR投げたときに、Dangerの警告で気づける方がスマートだ
  • 必要な情報が知るべきタイミングで共有される仕組みはとても良さそう
  • 実際のDangerfileには警告にesawikiへのリンクを追記してる

CircleCIからDangerを使うとき困ったこと

  • PRをGitHubから新規作成したときにDangerの実行がスキップされる
  • PRを作成した後にコミットをpushするとDangerは実行される
  • CircleCIがPR作成時に該当のPRのURLを環境変数に設定してないからスキップされるようだ
  • CircleCIの中の人曰く、今のところはPRを作った後にリビルドして対応してくれとのこと 😢
    • 解決方法は先頭に書いた!

For now, rebuilding is the only suggestion I have while our engineers look into this further.

https://discuss.circleci.com/t/circle-pull-request-not-being-set/14409/11discuss.circleci.com

https://discuss.circleci.com/t/trigger-new-build-on-pr/4219discuss.circleci.com

なぜCircleCIを選択したのか

  • 会社のCIツールを統一したくてCircleCIを選択した
  • しかし、CircleCIにこのような不便さがあるとは知らなかった
  • 個人開発では Bitrise を使っててPRの作成をトリガーに出来たので Bitrise に移行しようかなと心が揺れている 解決できた今はあまり揺れてない
  • せっかくCIツールを統一できて気持ち良い感じだったのに残念
  • 何か良い対策を知ってる人は教えてください 🙇‍♂️ 教えてくれました!

まとめ

  • CIからDangerを使うとPRの状態を自動チェックする仕組みがつくれる!!
  • 必要な情報が知るべきタイミングで共有される仕組みがつくれる!!
  • CircleCIから使うときは、Only Build pull requests を有効にしてPR作成時のスキップを回避しよう!!