GitHub Actions からボットによる Issue / Pull Request コメントを投稿する
結論から #
gh cli (v2.69.0+) で gh issue comment または gh pr comment コマンドを利用するのが簡単です。特に、ワークフローが繰り返し実行されコメントを更新していくような場合には --create-if-none, --edit-last オプションの組み合わせが便利です。
name: Comment
on:
workflow_dispatch:
jobs:
comment:
runs-on: ubuntu-latest
permissions:
# GITHUB_TOKEN の権限を指定 (コメントをするためには write 権限が必要です)
issues: write
steps:
# Issue #42 に Bot ユーザーによるコメントを追加します。
- run: |
gh issue comment 42 --body 'Hello, world!'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Note. checkout (clone) していないので、操作対象リポジトリを環境変数 GH_REPO で指定しています。
# checkout していればこれは省略できます。
# https://cli.github.com/manual/gh_help_environment
GH_REPO: ${{ github.repository }}
# Issue #42 における Bot ユーザーのコメントを更新 (upsert) します。
- run: |
gh issue comment 42 --edit-last --create-if-none --body 'Hello, world! (edited, ${{ github.run_id }})'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_REPO: ${{ github.repository }}
# GITHUB_TOKEN の権限でアクセスできるのは、このワークフローを実行しているリポジトリのみです。
# 他のリポジトリにアクセスしたり、あるいは、ボットユーザーを独自のボットユーザーにしたい場合、
# 適当な権限を持つ GitHub App を作成およびインストールし、その App の権限で gh コマンドを実行します。
- uses: actions/create-github-app-token@67018539274d69449ef7c02e8e71183d1719ab42 # v2.1.4
id: auth
with:
# secrets は設定済みであるとする。
app-id: ${{ secrets.APP_ID }}
private-key: ${{ secrets.APP_PRIVATE_KEY }}
- run: |
gh issue comment 42 --edit-last --create-if-none --body 'Hello, world! (by ${{ steps.auth.outputs.app-slug }}, ${{ github.run_id }})'
env:
GH_TOKEN: ${{ steps.auth.outputs.token }}
GH_REPO: ${{ github.repository }}

ボットによるコメントの例
詳細・議論 #
コメントの投稿は最終的には GitHub API を利用するわけですが、いくつかの手法があります。
- API を直接呼び出す
- トークンさえあれば、ドキュメントにある例のように curl コマンドなどを利用してコメントの投稿ができます。
- ただし、これは常にコメントを追加する呼び出しのため、既存のコメントを更新するような場合には分岐の実装が必要です。
- actions/github-script を利用する
- github.rest.issues.createComment が利用できます。
- API の wrapper にすぎないので、直接呼び出しと同様に、既存のコメントを更新するような場合には分岐の実装が必要です。
- gh cli を利用する
- gh issue comment が利用できます。
- 他の手法と比べたユニークな点として、このコマンドではオプションによりコメントの upsert 的な操作が簡単にできます。
- upsert のためだけに gh コマンドを使いたくない
- そういうこともありそうですが、コメント本文を生成するところだけ任意実装に切り出して、投稿は gh コマンドを使う、という組み合わせでよいのではないかと思いました。
jobs: comment: steps: - run: python generate_comment.py | gh issue comment 42 --edit-last --create-if-none --body-file=- - gh cli の実装としてはここらへんにあるとおり Get, Update, Create を素朴に呼び出しているだけなので、独自に実装する必要があっても難しくはないでしょう。
- App webhook などで呼び出されるサービス側に同様なことを実装する場合は必要かも
- そういうこともありそうですが、コメント本文を生成するところだけ任意実装に切り出して、投稿は gh コマンドを使う、という組み合わせでよいのではないかと思いました。
- コメントを upsert する?
- CI 的に実行されるなにかの処理の結果がワークフローのログにあるだけでは視認性が悪いとき、Pull Request に対してコメントとして投稿したいモチベーションがあります。
- たとえば、ユニットテストのエラーレポート, カバレッジ情報, terraform plan などです。
- CI 的に実行されるなにかの処理の結果がワークフローのログにあるだけでは視認性が悪いとき、Pull Request に対してコメントとして投稿したいモチベーションがあります。