💭

GitHub Actions から Pull Request にコメントする

2024/05/20に公開1

GitHub Actions からテストを動かして Pull Request の内容を検証するとき, テストサイズが Medium や Large になるとどうしてもテストが flaky になることを避けるのは難しくなります[1][2].

dependabot などを用いた依存ライブラリの定期的な更新ではCIによって自動でトランクブランチにマージされるようにしていると, この flaky なテストによってCIが失敗しマージされない場合が出てきます. このような場合は手動で検証しマージするコストがかかるため, テストが失敗しているかどうかにかかわらずマージしてしまったほうが良いという判断ができるでしょう[3]. とはいえテスト結果を無視すると以下のような問題が生じます.

  • 本当に失敗しているテストを見逃す.
  • flaky なテストを修正する機会を逃し, テストスイートの信頼性を下げる.

つまりCIとしては成功としていいが, テストが失敗していることは把握しておきたいということです.

GitHub Actions ではワークフローの実行結果に Annotation としてコメントを残すことができ[4], Jest にはこれを利用してテストが失敗していた場合にコメントを残すオプションが存在します[5].

ワークフロー上のメッセージの例
Jest 28: Shedding weight and improving compatibility 🫶 · Jest

この機能は Pull Request とも連携しており, 上の画像のように Pull Request のファイルの該当箇所に通知されます. しかしこの機能は GitHub の notification には表示されないため, Pull Request が自動でマージされる場合そのまま無視されてしまうでしょう.

そこで Pull Request にコメントすることでテストが失敗していることを通知します.

https://github.com/toms74209200/github-actions-test-pr

GitHub CLI を使えば簡単にコメントをつけることができます. コメントには先ほどの Annotation を参照するリンクをつけます.

テストが失敗した場合のみコメントするように if で条件分岐を行います. GitHub Actions では continue-on-error をつけることでステータスコードを無視して次の step に進むことができます. ただしここではステータスコードを変数に入れるときにステータスコードを無視しているため, つける必要はありません.

  - id: test
    name: Run tests
    continue-on-error: true
    run: |
      npm test || echo "status=$?" >> $GITHUB_OUTPUT
  - name: Create comment file
    if: ${{ steps.test.outputs.status != 0 }}
    run: |
      cat  << EOF > comment.md
      ## Test Failed
      The tests failed. Please check the logs for more information.
      https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}
      EOF
  - name: Create PR comment
    if: ${{ steps.test.outputs.status != 0 && }}
    run: |
      gh pr comment ${{ github.event.number }} --body-file comment.md
    env:
      GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

https://github.com/toms74209200/github-actions-test-pr/blob/master/.github/workflows/test.yml

このワークフローを再利用可能なワークフローとして利用します. 利用先でコメントするかどうかを選べるように設定可能にしておきます. Pull Request の場合にのみコメントするように github context[6] から github.event を取得して条件分岐することもできるはずですが, 今回はその方法は試していません.

Contexts - GitHub Docs

on:
  workflow_call:
    inputs:
      enable_pr_comment:
        description: 'Enable PR comment'
        required: false
        default: true
        type: 'boolean'
      - name: Create comment file
        if: ${{ steps.test.outputs.status != 0 && inputs.enable_pr_comment == true }}
        run: |
          cat  << EOF > comment.md
          ## Test Failed
          The tests failed. Please check the logs for more information.
          https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}
          EOF

これで Pull Request からこのワークフローが実行されるようにすると, 以下のようなコメントが投稿されます.

Pull Request のコメント.

https://github.com/toms74209200/github-actions-test-pr/pull/2

これで Pull Request の自動マージを実行しつつ, テストが失敗していることを通知できるようになりました. しかし本来であれば flaky なテストを修正することが望ましいです. テスト結果を集計して flaky なテストをきちんとトリアージして修正していくべきでしょう.

脚注
  1. Google Testing Blog: Test Sizes ↩︎

  2. 第3回 テストサイズ ~自動テストとCIにフィットする明確なテスト分類基準~ | gihyo.jp ↩︎

  3. Pull Request でのCI検証とは別にデプロイメントパイプラインでの検証を行うことで最終的なリスクを下げるといった方法を取ることもできます. Shift-Left の考え方から外れることになるため, リスク許容度による判断が必要です. ↩︎

  4. Annotations, how to create them? · community · Discussion #26703 ↩︎

  5. GitHub Actions Reporter - Jestの設定 · Jest ↩︎

  6. Workflow syntax for GitHub Actions - GitHub Docs ↩︎

Discussion