This is my life.

There are many like it, but this one is mine.

GitHub Actions で Pull Request のチェックをする

前回の記事GitHub Actions を使って push の度に test を動かす方法を紹介しました。

今回は、 Pull Request で実行する Workflow を作ってみたいと思います。
(2018/12/24 現在、 Pull Request での実行は private repository のみでの提供となっています。)

Pull Request をワークフローのトリガーにする

Pull Request で Workflow を実行するには、on attribute を pull_request にします。

workflow "NAME_OF_WORKFLOW" {
  on = "pull_request"
  ...
}

その他、対応しているトリガーを確認したい場合 公式ドキュメント に詳しく記述されています。
※ Pull Request の場合、 Review Request( review_requested ) や タイトルの変更( edited ) など、Pull Request に関わる多くのイベントに対して実行されます。Pull Request 内のコミットに対してのみワークフローを実行したい場合、Actionでは synchronized に対して実行するなどのフィルターが必要になるでしょう。 Event Types & Payloads | GitHub Developer Guide

上記のようにAction内で更に特定の条件を追加したい場合、Payload を扱うことができます。Payload は JSON形式のファイルとして 環境変数 GITHUB_EVENT_PATH のパスに配置されています。( Accessing the runtime environment | GitHub Developer Guide )

コンテナ内で jq コマンドなどを利用することで、Eventに関する特定の情報を取得することができます。
例えば以下のコマンドで Pull Request 番号 を取得することができます。

cat $GITHUB_EVENT_PATH | jq -r ".number"

GITHUB_TOKEN を払い出す

今回 Pull Request のチェックに利用しようとしている Danger は、Pull Request に対してコメントをすることができます。
その他 Pull Request の情報を取得するために Personal Access Token が必要になります。

Personal Access Token を利用してコメントを行った場合、トークンを払い出したアカウントがコメントを行うことになります。
チームなどで開発する際は bot account を作成し、そちらからトークンを払い出す。といった運用を行うことになります。

これが、 GitHub Actions では GITHUB_TOKEN という環境変数で払い出されます。(Storing secrets | GitHub Developer Guide

こちらを利用することで、 bot account を作成しなくても人に依存しないトークンを利用することができます。 個人的に非常に魅力的な機能で、 GitHub Actions ならではの優位性だと感じています。

利用するには action ブロックで secretsGITHUB_TOKEN を追加します。

 action "Danger" {
   ...
   secrets = ["GITHUB_TOKEN"]
 }

Action を作成する

Danger を利用して Pull Request をチェックする Action を作成してみましょう。
前回の記事でも紹介したとおり、Dockerfileで定義します。

FROM ruby:2.5-alpine

LABEL "repository"="https://github.com/duck8823/actions"
LABEL "homepage"="https://github.com/duck8823/actions"
LABEL "maintainer"="<shunsuke maeda> duck8823@gmail.com"

LABEL "com.github.actions.name"="Danger"
LABEL "com.github.actions.description"="Run Danger"
LABEL "com.github.actions.icon"="alert-triangle"
LABEL "com.github.actions.color"="yellow"

RUN apk update \
 && apk add git \
 && rm -rf /var/cache/apk/*

RUN gem install danger

ADD . .

CMD "danger"

必要な依存が最低限と、実行コマンドのシンプルな Dockerfile です。
LABEL を利用することで、 GUI での見た目を変更することができます。
ここでは Danger というツールを使うので、それっぽいアイコンにてみました。
f:id:duck8823:20181224123640p:plain

icon は 以下のものが利用できるようです。
feathericons.com

なお、 Danger では 各CI に対してクラスを定義する仕組みなので、上記 Pull Request 番号の取得方法などを踏まえて PR を出しました。既にマージしていただいているので、利用することができます。

github.com

Action を利用する

定義した Action の利用方法は前回の記事のとおりですが、今回は汎用的な処理なので別のリポジトリに定義したActionを配置しました。
github.com

Action は action ブロックの uses で定義しますが、指定方法もいくつかあります。 (Workflow configuration options | GitHub Developer Guide)

GitHub に置かれた Action であれば {owner}/{repo}/{Dockerfileが置かれたディレクトリまでのpath}@{ref} で指定できます。

 action "Danger" {
   uses = "duck8823/actions/danger@master"
   ...
 }

Danger で Pull Request をチェックする

Danger は Dangerfile というファイルを定義し、その内容によって Pull Request の内容をチェック・コメントするツールです。

warn("diff が大きいぞ") if git.lines_of_code > 500

以下の記事で簡単に紹介しています。
blog.duck8823.com

記事内容では bundler でインストールしていますが、作成した Action ではコンテナに直接 danger をインストールしています。
プラグインなどを利用したい場合は、 bundler/inline を利用して実行時にインストールすることができるでしょう。

実際に Danger を実行し、定義したチェックを全てパスすると Commit Status が作成されます。その際 GitHub Actions で払い出されたTokenを利用したので @github-actions が作成したことになっています。

f:id:duck8823:20181224131308p:plain

出来上がったワークフロー

完成したワークフローは以下のとおりです。かなりシンプルに表現できていると思います。 対象リポジトリで行うことは、下記ワークフローの定義と、実際にチェックをするための Dangerfile の作成になります。

workflow "Check Pull Request" {
  resolves = ["Danger"]
  on = "pull_request"
}
 
action "Danger" {
  uses = "duck8823/actions/danger@master"
  secrets = ["GITHUB_TOKEN"]
}

まとめ

おまけ

さて、最初に紹介したとおり pull_request をトリガーにするとレビューワーの追加などでもワークフローが実行されます。 CommitStatus はそれぞれ別に作成するようで...