🐙

[GitHub] 関連するプルリクをレポートするワークフロー

2024/05/23に公開

下記のような GitHub Actions のワークフローを用意して、プルリク時に動かすようにします。

.github/workflows/associated-pr-report.yml
name: Associated PR Report

on:
  pull_request:
    types:
      - opened
      - edited
      - reopened
      - synchronize

concurrency:
  group: ${{ github.workflow }}-${{ github.head_ref }}
  cancel-in-progress: true

jobs:
  report:
    name: PR report
    runs-on: ubuntu-latest
    permissions:
      pull-requests: write # for GitHub CLI and yumemi-inc/comment-pull-request
    steps:
      - name: Get PR numbers
        id: get-numbers
        env:
          GH_REPO: ${{ github.repository }}
          GH_TOKEN: ${{ github.token }}
          HEAD_PR_NUMBER: ${{ github.event.pull_request.number }}
        run: |
          sha_list="$(gh api "repos/{owner}/{repo}/pulls/${HEAD_PR_NUMBER}/commits" --paginate | jq -r '.[]|select(.parents|length>1)|.sha')"
          for sha in $sha_list ; do
            pr_number_list="$(gh api "repos/{owner}/{repo}/commits/${sha}/pulls" | jq '.[].number|select(.!='"${HEAD_PR_NUMBER}"')')"
            for pr_number in $pr_number_list ; do
              pr_number_array+=("$pr_number")
            done
          done
          unique_pr_number_list="$(echo "${pr_number_array[@]}" | tr ' ' '\n' | sort -u)"
          {
            delimiter="$(openssl rand -hex 8)"
            echo "markdown<<$delimiter"
            for pr_number in $unique_pr_number_list ; do
              echo "- #${pr_number}" # markdown format
            done
            echo "$delimiter"
          } >> "$GITHUB_OUTPUT"
      - name: Comment
        if: steps.get-numbers.outputs.markdown != null
        uses: yumemi-inc/comment-pull-request@v1
        with:
          comment: |
            ### pull requests merged into this pull request:
            ${{ steps.get-numbers.outputs.markdown }}
          previous-comment: 'hide'

プルリクのコミットの中に、 別のプルリクに関係するものが含まれている場合、次のようにコメントされます。

例えば git-flow でブランチ運用している際に、リリース用のプルリク(修正した全ファイルが含まれるプルリク)でこのワークフローを動かしておくと、リリースに含まれるプルリクがどれかか確認できて便利そうです。

ワークフローに関する補足説明

pull_request:
  types:
    - opened
    - edited
    - reopened
    - synchronize

edited で、プルリクの base ブランチを変更した際にもワークフローを動かすようにしています。base によってプルリクに含まれるコミットは変わってくる為。

concurrency:
  group: ${{ github.workflow }}-${{ github.head_ref }}
  cancel-in-progress: true

今回は edited イベントのようなプルリク画面での画面操作時にもこのワークフローが動く為、画面(や Git)の操作順と、ワークフローの実行順が同じになるようにしています。このワークフローの実行時間は短い為、実行中のワークフローはキャンセルさせる必要は必ずしもありませんが、このワークフローの内容からいってとくにキャンセルしない理由も無いので、cancel-in-progresstrue を指定しています。でもここは、どちらでもよいと思います。

sha_list="$(gh api "repos/{owner}/{repo}/pulls/${HEAD_PR_NUMBER}/commits" --paginate | jq -r '.[]|select(.parents|length>1)|.sha')"

parents(コミットの親)が複数のコミットのみを取得しています。

pr_number_list="$(gh api "repos/{owner}/{repo}/commits/${sha}/pulls" | jq '.[].number|select(.!='"${HEAD_PR_NUMBER}"')')"

コミットに関連するプルリクの番号を取得しています。この際、マージ前のプルリクには自身のプルリク番号が含まれるようなので、それは除くようにしています。

for pr_number in $pr_number_list ; do
  pr_number_array+=("$pr_number")
done

恐らく $pr_number_list は0件、もしくは1件になるとは思うのですが、REST API の仕様上は複数件がか返るので、念の為、複数件を想定して処理しています。

unique_pr_number_list="$(echo "${pr_number_array[@]}" | tr ' ' '\n' | sort -u)"

手動マージ(または GitHub プルリク画面における base 取り込みの操作)のコミットを含むプルリクが本プルリクにマージされている場合、手動マージのコミットから得られる番号と、プリリクのマージコミットから得られるプルリク番号が同一となり重複するので、重複は排除しています。

{
  delimiter="$(openssl rand -hex 8)"
  echo "markdown<<$delimiter"
  for pr_number in $unique_pr_number_list ; do
    echo "- #${pr_number}" # markdown format
  done
  echo "$delimiter"
} >> "$GITHUB_OUTPUT"

markdown形式で output しています。この output は後続のコメントの step で利用します。

追記(2024.5.25)

上記のワークフローは、costom action として切り出しました。是非こちらをご利用ください。

https://github.com/marketplace/actions/associated-pull-requests

任意の2つのコミット(or タグ or ブランチ)の間のコミット郡に関わるプルリクの一覧が取得できるようになっているので、例えば main ブランチと develop ブランチ間のプルリクを全て取得するようなことが出来ます。

そのほか参考

リリースに関しては、下記投稿のようなワークフローも用意しておくとよいかもです。

https://zenn.dev/yumemi_inc/articles/02044be92c517a

株式会社ゆめみ

Discussion