LoginSignup
28

More than 3 years have passed since last update.

GitHub Actions でプルリクエストの自動アサインをする

Last updated at Posted at 2019-12-10

これは ゆめみ Advent Calendar 2019 の10日目の投稿です。

皆さんはもう GitHub Actions を使っていますでしょうか?便利ですよね。

CI(継続的インテグレーション)でテストしたりビルドしたりするのに利用することが多いかと思いますが、GitHub 上の作業を自動化するのにも使えたりします。

今回は、プルリクエストを作成したら自動で AssigneesReviewers を設定するワークフローを紹介します。
(毎回これらが決まりきっている場合、プルリクエストを作る毎に設定するのは面倒ですよね。)

参考

Assignees の自動設定

assignees は基本的には当該プルリクエストの対応(レビューの対応)をする人になると思うので、プルリクエストを作成した本人とします。
ワークフローの設定は次のようになります。

.github/workflows/assign-auto.yml

name: Assign auto

on:
  pull_request:
    types: opened # プルリクを作成したタイミングだけで動かす

jobs:
  assign:
    name: Set assignees
    runs-on: ubuntu-18.04
    steps:
      - name: Set assignees
        env:
          ASSIGNEES: "${{ github.actor }}" # 変えたければここを変える
        run: |
          assignee_count=$(cat ${{ github.event_path }} | jq '.pull_request.assignees | length')
          if [[ 0 == $assignee_count ]]; then
            assignees=$(echo "\"${ASSIGNEES// /}\"" | jq 'split(",")')
            curl -X POST \
                 -H "Content-Type: application/json" \
                 -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
                 -d "{ \"assignees\": $assignees }" \
                 https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/assignees
          fi

${{ github.XXX }} は公式ドキュメントを見てもらえば分かりますが、GitHub 上の情報(今回はプルリクエスト)を参照する構文です。勘違いしやすいのですが、環境変数ではありません。「実行前に静的に文字列置換される」という感覚が近いです。${{ secrets.GITHUB_TOKEN }} も標準で利用できる構文で、GitHub API アクセス用のトークンに置き換えられます。

assignee_count はプルリク作成と同時に設定された assignees の数です。これがゼロの場合に curl コマンドで GitHub API を叩いて assignees を設定します。

assignees=$(echo "\"${ASSIGNEES// /}\"" | jq 'split(",")') の箇所が少し分かりづらいので補足します。仮に環境変数 ASSIGNEES に設定されたアカウントが hoge, fuga とすると、

  1. ${ASSIGNEES// /} でスペースを削除 .. hoge,fura
  2. "\"${ASSIGNEES// /}\"" でダブルクォートを付加しJSONの文字列とする(後続のjqコマンドで扱えるようにする) .. "hoge,fuga"
  3. jq 'split(",")'jqコマンドにより文字列をJSONの配列にする .. [ "hoge", "fuga" ]

といったことをしています。

Reviewers の自動設定

ワークフローの設定は次のようになります。

.github/workflows/assign-auto.yml
name: Assign auto

on:
  pull_request:
    types: opened

jobs:
  assign:
    name: Set reviewers
    runs-on: ubuntu-18.04
    steps:
      - name: Set reviewers
        env:
          REVIEWERS: "hoge, fuga, piyo" # edit here
        run: |
          reviewer_count=$(cat ${{ github.event_path }} | jq '.pull_request.requested_reviewers | length')
          if [[ 0 == $reviewer_count ]]; then
            reviewers=$(echo "\"${REVIEWERS// /}\"" | jq 'split(",") | .-["${{ github.actor }}"]')
            curl -X POST \
                 -H "Content-Type: application/json" \
                 -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
                 -d "{ \"reviewers\": $reviewers }" \
                 https://api.github.com/repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/requested_reviewers
          fi

assignee の設定とあまり変わらないので説明は割愛しますが、プルリクを作成した本人は reviewers から除外している(レビュアに設定する必要がないし、GitHub API でもエラーになる)ことだけ注意です。

まとめると

上記2つのワークフローをまとめると次のようになります。

.github/workflows/assign-auto.yml
name: Assign auto

on:
  pull_request:
    types: opened

jobs:
  assign:
    name: Set assignees and reviewers
    runs-on: ubuntu-18.04
    steps:
      - name: Set assignees
        env:
          ASSIGNEES: "${{ github.actor }}"
        run: |
          assignee_count=$(cat ${{ github.event_path }} | jq '.pull_request.assignees | length')
          if [[ 0 == $assignee_count ]]; then
            assignees=$(echo "\"${ASSIGNEES// /}\"" | jq 'split(",")')
            curl -X POST \
                 -H "Content-Type: application/json" \
                 -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
                 -d "{ \"assignees\": $assignees }" \
                 https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/assignees
          fi
      - name: Set reviewers
        env:
          REVIEWERS: "hoge, fuga, piyo" # edit here
        run: |
          reviewer_count=$(cat ${{ github.event_path }} | jq '.pull_request.requested_reviewers | length')
          if [[ 0 == $reviewer_count ]]; then
            reviewers=$(echo "\"${REVIEWERS// /}\"" | jq 'split(",") | .-["${{ github.actor }}"]')
            curl -X POST \
                 -H "Content-Type: application/json" \
                 -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
                 -d "{ \"reviewers\": $reviewers }" \
                 https://api.github.com/repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/requested_reviewers
          fi

もしブランチ毎に reviewers が異なる、という場合は、ワークフローの実行条件のところでブランチを指定するか(yamlファイルはブランチ分用意する)、

on:
  pull_request:
    branch:
      - master

もしくは steps 内で

- name: Set reviewers
  if: github.base_ref == 'master'
- name: Set reviewers
  if: startsWith(github.base_ref, 'develop') # 前方一致

のようにして各ステップを実行するか否かを制御すればいいでしょう。

今回は固定メンバーを全員 reviewrs として設定していますが、スクリプトを工夫すればランダムに選択して設定、等もできると思います。

おわりに

いかがだったでしょうか。もし他に良い利用事例があれば、紹介いただけると幸いです。
それではよい GitHub Actions ライフを!

2020年10月26日 追記

上記の機能+αを、独立した GitHub の Action として切り出しました。

この Action を利用すると、次のようにシンプルに書けます :smile:

.github/workflows/review-assign.yml
name: Review Assign

on:
  pull_request:
    types: [opened, ready_for_review]

jobs:
  assign:
    runs-on: ubuntu-latest
    steps:
      - uses: hkusu/review-assign-action@v0.1.0
        with:
          assignees: ${{ github.actor }}
          reviewers: hoge, fuga, piyo

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
28