Pull RequestのコメントからGitHub Actionsを実行する

GitHubのPull Requestのコメントから任意のGitHub Actionsを実行する必要があり、やり方に少々癖があったので紹介します。

issue_comment

ドキュメントを眺めているとPull Requestに関連するイベントはいくつかありますが、Pull Requestのコメントをトリガーとしたイベントが無いように見えます。

どうにかPull Requestのコメントをトリガーに起動できないか調べていたらCommunity Forumで以下の投稿を見つけました。

github.community

この投稿によるとissue_commentイベントでPull Requestのコメントもトリガーとなるようです。
Issueへのコメントもトリガーの対象となるので、適切にフィルタリングする必要があると書かれています。

実装

今回は/planとコメントに入力することでterraform planが実行されるGitHub Actionsを作ってみたいと思います。

stepsまでのコードが以下になります。

name: "/plan"
on:
  issue_comment:
    types: [created, edited]

jobs:
  manual_plan:
    name: "manual plan"
    if: contains(github.event.comment.html_url, '/pull/') && startsWith(github.event.comment.body, '/plan')
    runs-on: [ubuntu-latest]
    steps:

ポイントはジョブ全体でifを設定して起動する条件を設定しているところです。

contains()でPull Requestのコメントのみに反応するようにし、startsWith()/planとコメントに入力された場合のみにしています。

実行されるブランチ

上記の設定のままstepsで処理を書いていけば意図した通りに動作しそうですが、1つ問題があります。
issue_commentをトリガーとした場合、actions/checkoutでpullできるブランチがmasterブランチになってしまいます。(正確にはリポジトリのデフォルトブランチ)

Pull Requestのコメントで実行するので、そのPull Requestのブランチでジョブを実行したいです。

actions/checkout@v2からはブランチを指定してpullできるようになりました。
Actionsをトリガーした内容が入った変数、つまり${{ github }}をもとにGitHubAPIを使ってPull Requestのブランチ名を取得します。
それをactions/checkout@v2にセットし、Pull Requestのブランチでジョブを実行できるようにします。

    steps:
      - name: get upstream branch
        id: upstreambranch
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          echo "::set-output name=branchname::$(curl -H "Authorization: token ${GITHUB_TOKEN}" ${{ github.event.issue.pull_request.url }} | jq '.head.ref' | sed 's/\"//g')"

      - name: Checkout upstream repo
        uses: actions/checkout@v2
        with:
          ref: ${{ steps.upstreambranch.outputs.branchname }}

Pull Requestに結果を書き込み

せっかくなのでplanの結果をPull Requestのコメントに書き込みたいと思います。

GitHubに関連する操作はactions/github-scriptを使えば大体の事ができます。

github.com

      - id: plan
        run: terraform plan -no-color

      - name: plan success message
        uses: actions/github-script@0.9.0
        if: steps.plan.outputs.exitcode == 0
        env:
          STDOUT: "```${{ steps.plan.outputs.stdout }}```"
        with:
          github-token: ${{secrets.GITHUB_TOKEN}}
          script: |
            github.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: "#### `terraform plan` Success\n" + process.env.STDOUT
            })