Github Actionsを使ってPull Requestオープン時にCircleCIを実行する

CircleCIで確実にDangerやreviewdogを動かす方法

Soudai Sasada

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 トークンを作成できます。

  1. パーソナル: このトークンは CircleCI API とのやり取りに使用され、完全な読み取りアクセス権と書き込みアクセス権を付与します。
  2. プロジェクト: このトークンは、特定のプロジェクトに関する情報を提供し、読み取りアクセス権のみを付与します。

https://circleci.com/docs/ja/2.0/managing-api-tokens/

パーソナルトークンはCircleCIのユーザー設定から作成できます。

circleci-account-link-within-sidebar

circleci-personal-api-tokens-within-account-page

プロジェクトから属人性を排除するためには組織で独立したGithubアカウント/CircleCIアカウントを用意しそのアカウントのトークンを使う方が良いかもしれません(もしそのようなアプローチで運用するのであれば予めその使い方がGithubやCircleCIの規約に違反していないか事前に必ずそれぞれチェックしましょう)。

次にCircleCIのパーソナルトークンをGithub Actionsで使えるようGithubのSecretsへ追加します。設定したいリポジトリでSettingsタブが表示されない場合には自身の権限では当該リポジトリの設定変更をできない可能性が高いです。その場合にはチーム内で相談し権限を持つメンバーに設定してもらうなり権限を付与してもらうなり調整しましょう。

github-settings-page

github-actions-secrets-page

github-actions-secrets-new-secret-page

最後にGithub Actionsを設定します。

pull_requestで指定するbranchesbaseブランチとなります。なのでもしここに!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に組み込むと良いかもしれません。

.github/workflows/main.yml
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を触りましたが想像以上に手軽で驚きました。ドキュメントを見ると他にも色々とできそうなので時間があるときにまた詳しく調べてみようと思います。

この記事がお役に立てたら一杯のコーヒーを恵んで頂けると励みになります 😊

Buy Me A Coffee
© 2020, Soudai Sasada