GitHub Actions で Pull Request にコメントをつける

前回の GitHub Actions を fork して利用する に引き続き GitHub Actions 周りを調べている。
今回は Pull Request にコメントする方法を調べていた。

TL;DR

name: CI
on: [push]
jobs:
  gh-sample:
    runs-on: codebuild-<project-name>-${{ github.run_id }}-${{ github.run_attempt }}
    steps:
      - uses: actions/checkout@v3
      
      # ①
      # Self Hosted Runner の場合には手動でインストールする必要がある
      # GitHub.com がホストしているランナーには pre-install 済みなのでインストールの必要なし
      # https://docs.aws.amazon.com/codebuild/latest/userguide/action-runner.html で CodeBuild を Self Hosted Runner として動かしている例
      - name: install gh
        run: sudo yum install -y https://github.com/cli/cli/releases/download/v2.50.0/gh_2.50.0_linux_386.rpm
      
      # ②
      # 複数行のコメントを一時的に変数に格納しておく
      # see also https://docs.github.com/ja/actions/using-workflows/workflow-commands-for-github-actions#multiline-strings
      - name: save multiline comment to env
        run: |
          {
            echo "GH_SAMPLE_COMMENT<<EOF"
            echo "This"
            echo "is"
            echo "multiline"
            echo "comment"
            echo EOF
          } >> "$GITHUB_ENV"
      
      # ③
      # `--edit-last` でコメントを上書きできるのだが、 https://github.com/cli/cli/issues/6790 によるとコメントがない場合には失敗するので upsert 的なことを自前でする必要がある
      - name: Add Commnet to Pull Request
        run: gh pr comment ${{ github.ref_name }} --body "${{ env.GH_SAMPLE_COMMENT }}" --edit-last || gh pr comment ${{ github.ref_name }} --body "${{ env.GH_SAMPLE_COMMENT }}"
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          # GitHub Enterprise では以下の env が必要だった
          # see also https://cli.github.com/manual/gh_help_environment
          # GH_ENTERPRISE_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          # GH_HOST: "your.host.com"
      
      # ④
      # GitHub Actions の Job Summaries にも書くことができる
      # see also https://docs.github.com/ja/actions/using-workflows/workflow-commands-for-github-actions#adding-a-job-summary
      - name: Add to Job Summaries
        run: echo "${{ env.GH_SAMPLE_COMMENT }}" >> "$GITHUB_STEP_SUMMARY"

詳細

多分上を見ればわかってしまうが、ここではそれぞれについて参照すべきドキュメントへのリンクなどを残すことでちょっとでも調べる手間を省けるようにする

gh をインストールする

ワークフローで GitHub CLI を使用する にある通り、

GitHub CLI は、GitHub でホストされるすべてのランナーにプレインストールされます。 GitHub CLI を使う各ステップで、GH_TOKEN という環境変数に必要なスコープを持つトークンを設定する必要があります。

GitHub がホストしているランナーには漏れなくインストールされているためすぐに使うことができる。
が、Self Hosted Runner では自分でインストールする必要があるため https://github.com/cli/cli#installation などを参照の上別途インストールする。

② ステップ間で共有する値を一時的に格納する

Step 間で共有したいようなものは、GITHUB_ENV に Key-Value の形で書き込むことで実現できる。
複数行の文字列については、 複数行の文字列 にもあるように以下の形式で書ける。

{name}<<{delimiter}
{value}
{delimiter}

具体的には、上部にもあるようにこんな感じで ${{ env.GH_SAMPLE_COMMENT }} でアクセスすることができる。

- name: save multiline comment to env
  run: |
    {
      echo "GH_SAMPLE_COMMENT<<EOF"
      echo "This"
      echo "is"
      echo "multiline"
      echo "comment"
      echo EOF
    } >> "$GITHUB_ENV"

また、Job 間で変数を共有したい場合には 出力パラメータの設定 にもあるように GITHUB_OUTPUT を利用するらしい。

③ Pull Request にコメントする

gh を利用して Pull Request にコメントをしている部分。
(そもそも gh とは?という人には丁寧なマニュアルがおすすめ)

gh pr comment にもある通り --edit-last というフラグを付与すれば、その作者が (今回でいうと GitHub Actions のbot が) 最後にコメントしたコメントを更新することができるので、実行のたびにコメントが追加されていかなくて例えばカバレッジのレポートを表示したりするのに都合が良い。

がなんと、https://github.com/cli/cli/issues/6790 にもあるようにコメントがない場合には、エラーとなってしまう。

$ gh pr comment 5 --edit-last --body 'This is just a test'
-> no comments found for current user

そのため、https://github.com/cli/cli/issues/6790#issuecomment-1376009457 でも提案されているように、
まずは、更新を試みてみてエラーになったらコメントするという形で書く必要がある。

また gh を利用するにあたって設定すべき環境変数などは https://cli.github.com/manual/gh_help_environment に書いてあるので参照すること。

ちなみに コンテキスト にもあるようにイベントによって取得できる値が異なるケースが多いのでそこも注意すること。
例えば、 ${{ github.ref_name }} は、以下のように説明されており、 push では実際のブランチ名が取得できるが pull_request イベントでは、 /merge という文字列が入ってきたりするので gh pr comment にそのまま利用できなかったりする。

ワークフローの実行をトリガーしたブランチまたはタグの短い参照名。 この値は、GitHub に表示されるブランチまたはタグ名と一致します。 たとえば、feature-branch-1 のようにします。

プルリクウェストの場合、形式は /merge。

④ Job Summaries に表示する

これは完全に余談で、 GitHub Actions の Job Summaries という表示箇所がある。
Supercharging GitHub Actions with Job Summaries にもある通り、ここに様々な情報を残せるようになっていて、以下のように $GITHUB_STEP_SUMMARY に書き込むだけで表示することができる。

steps:
  - name: Adding markdown
    run: echo '### Hello world! 🚀' >> $GITHUB_STEP_SUMMARY

ちなみに ジョブの概要の追加 にも詳細な説明がされている。