Github Actionsを使ってPull Requestオープン時にCircleCIを実行する
CircleCIで確実にDangerやreviewdogを動かす方法
Soudai Sasada
Dangerやreviewdogというツールをご存知でしょうか?これらはコードレビューを補助してくれるツールでどちらもCIと組み合わせることでBotが自動でレビューしてくれるツールとなります。
たとえば「Pull Requestの差分が400行を超えたら警告する」、「変更に対するLinterの実行結果をインラインコメントの形で投稿する」といった具合にソースコードの差分に対して自身が設定したルールを自動でフィードバックすることができるので、コードレビュー時の見落としを防いだりリポジトリ特有のルールを適用するうえで便利なツールです。
筆者はリポジトリ管理にGithub、CI/CDにCircleCI、コードレビューの補助にはDangerを使うケースが多いのですが、DangerやreviewdogはPull Requestがないとレビューすることができません。なのでコミット時にCircleCIのビルドを走らせる(デフォルトの)設定になっているとPull RequestをオープンするためにGithubへPushしてもそのタイミングで走るCIのビルドではレビューされません。
この問題への対処としてCircleCIでOnly build pull requests
をオンに設定することで回避できます。この設定をするとオープンされているPull Requestのheadブランチに対してのみCIのビルドが走ります。Pull Requestがない状態ではビルドは走らず、Pull Requestのオープン時、オープンしているPull Request上のコミットに対してのみビルドが走るようになるためです。
この設定で問題がない場合にはこれで解決となりますが、リリースフローとしてPull Requestのbaseブランチをdevelopやmasterへ向けそれらのブランチへのマージコミット時にリモート環境へのデプロイが走るように設定している場合、Only build pull requests
をオンに設定していると(予めそれらのブランチをheadブランチとしたPull Requestを用意しない限り)ビルドが走らなくなってしまいます。
Pull Requestのオープン時にDangerやreviewdogを使って自動レビューを機能させつつ、特定のブランチへのマージコミットをトリガーに自動でデプロイするためにはいくつかのアプローチが考えられますが、筆者はCircleCIのOnly build pull requests
はオフのままGithub Actionsを使ってPull Requestのオープン時にCircleCIのビルドを走らせるようにすることにしました。
Github ActionsでPull Requestのオープン時にCircleCIのビルドを走らせる
Github Actionsは様々なトリガーがありPull Requestのオープン時というトリガーも設定できます。今回はこのトリガーでCircleCIのAPIを叩きビルドを走らせることで新しくオープンされたPull Requestに対し確実にCircleCIを走らせCirlcleCI上でDangerの自動レビューが反映されるようにします。
まずはCircleCIを叩くためにCircleCI上でトークンを生成します。必要となるトークンはプロジェクトのトークンではなくパーソナル(ユーザーごとの)トークンのためご注意ください。
CircleCI では 2 種類の API トークンを作成できます。
- パーソナル: このトークンは CircleCI API とのやり取りに使用され、完全な読み取りアクセス権と書き込みアクセス権を付与します。
- プロジェクト: このトークンは、特定のプロジェクトに関する情報を提供し、読み取りアクセス権のみを付与します。
パーソナルトークンはCircleCIのユーザー設定から作成できます。
プロジェクトから属人性を排除するためには組織で独立したGithubアカウント/CircleCIアカウントを用意しそのアカウントのトークンを使う方が良いかもしれません(もしそのようなアプローチで運用するのであれば予めその使い方がGithubやCircleCIの規約に違反していないか事前に必ずそれぞれチェックしましょう)。
次にCircleCIのパーソナルトークンをGithub Actionsで使えるようGithubのSecretsへ追加します。設定したいリポジトリでSettingsタブが表示されない場合には自身の権限では当該リポジトリの設定変更をできない可能性が高いです。その場合にはチーム内で相談し権限を持つメンバーに設定してもらうなり権限を付与してもらうなり調整しましょう。
最後にGithub Actionsを設定します。
pull_request
で指定するbranches
はbaseブランチとなります。なのでもしここに!develop
という指定をしてしまうと develop
をbaseブランチとするPull Requestは全て対象外となってしまうため注意が必要です。この記事ではbranches
を使い!master
という指定をすることでmasterブランチへのPull Request作成時には走らせないようにしていますがGithub Actionsではbranches
以外にbranches_ignore
という指定も可能なのでどちらを使っても問題ないです。ただし両方設定することはできないのでどちらか都合の良い方を選択しましょう。ドキュメントが充実しているので分からないことがあればまずドキュメントを見ることをお勧めします。なお先ほどGithubのSecretsに設定したCircleCIのパーソナルトークンはsecrets.${GithubのSecretsとして登録した名前}
で取得ができます(この例ではCIRCLE_TOKEN
という名前で登録しています)。
Github ActionsのrunステップではCircleCIのtriggerPipelineというAPIを叩いています。
筆者が試したところCircleCIのAPIはエラーメッセージがやや分かりづらかったので、切り分けのためにまずはローカルマシン上で叩いて動作を確認してからGithub Actionsに組み込むと良いかもしれません。
name: Run CircleCI when pull request opened
on:
pull_request:
branches:
- '**'
- '!master'
types:
- opened
- reopened
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Run CircleCI
env:
CIRCLE_BRANCH: ${{ github.head_ref }}
CIRCLE_TOKEN: ${{ secrets.CIRCLE_TOKEN }}
run: |
curl -X POST \
-u "$CIRCLE_TOKEN:" \
-H 'Content-Type: application/json' \
-d "{\"branch\":\"$CIRCLE_BRANCH\"}" \
--url "https://circleci.com/api/v2/project/gh/$GITHUB_REPOSITORY/pipeline"
これでPull RequestのオープンをトリガーにしてGithub Actions経由でCircleCIのビルドをAPI経由で走らせることができるようになりました。Only build pull requests
はオフのままなので特定ブランチへのマージコミットをフックにしたデプロイもこれまでどおり行われPull Requestオープン時にDangerやreviewdogによる自動レビューも実行されます。
なおGithub Actionsは実行時間単位での課金ですが今のところキャッシュありでだいたい1秒前後、キャッシュなしで15秒前後で終わるためキャッシュヒット率を低めに2割、それぞれ多めに2秒/20秒と見積もっても無料枠の上限となる2000分/月までPull Requestを200回作れる計算となり小さいプロジェクトであれば無料の枠内に収まるかと思います(これはかなり悲観的な見積もりなので実際にはもっと余裕はあるでしょう)。GithubのPull Request作成をトリガーにGithub Actionsを動かしていることもあり最低限の設定で済むので手間はもちろん実行時間のロスも少なく目的に対し合理的な選択肢の一つと言えるのではないでしょうか。
今回初めてGithub Actionsを触りましたが想像以上に手軽で驚きました。ドキュメントを見ると他にも色々とできそうなので時間があるときにまた詳しく調べてみようと思います。