🍡

actions/github-script を使って Pull Request のレビュワーに自動アサインする

2023/03/15に公開

はじめに

Pull Request を作成するたびに手動で任意のレビュワーをアサインするのは面倒です。
では、コードオーナーを指定して常に一定の人をアサインすれば良いかというと、チームメンバー全員をアサインすることになったり、レビュワーが固定化されてしまう可能性があります。
ということで、Pull Request 作成時に、特定のグループから一人づつランダムに自動でアサインする GitHub Actions のワークフローを作成してみました。

actions/github-script とは

actions/github-script は GitHub API の呼び出しを JavaScript で書ける公式の Action です。
サードパーティの Action を使いたくないという時や GitHub のちょっとした操作を簡単に行いたいといった場合に有用です。
実態の処理は octokit/rest.js で行われているので、操作する時はこちらのドキュメントを参照すると使い方が分かりやすいです。

GitHub Actions の実装

今回の GitHub Actions の実装はこちらです。
assignees には Pull Request の作成者をアサイン、
reviewers にはグループとメンバーを定義して、それぞれのグループから一人ずつランダムに抽出してアサインしています。
その時、reviewers には Pull Request の作成者はアサインできないので除いています。

name: Auto assign pull requests

on:
  pull_request:
    types: [opened]

permissions:
  pull-requests: write
  issues: read

jobs:
  assign:
    name: Assign assignees and reviewers
    runs-on: ubuntu-latest
    steps:
      - name: Assign Pull Request Author as Assignee
        uses: actions/github-script@v6
        if: ${{ toJSON(github.event.pull_request.assignees) == '[]' }} # Assignees を設定していない時だけ動かす
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          script: |
            const { number, user } = context.payload.pull_request;
            await github.rest.issues.addAssignees({
              owner: context.repo.owner,
              repo: context.repo.repo,
              issue_number: number,
              assignees: [user.login]
            });
      - name: Assign random reviewers
        uses: actions/github-script@v6
        if: ${{ toJSON(github.event.pull_request.requested_reviewers) == '[]' }} # Reviewers を設定していない時だけ動かす
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          script: |
            // 任意のグループとメンバーを定義
            const groups = {
              group1: ['user1', 'user2', 'user3'],
              group2: ['user4', 'user5', 'user6'],
              group3: ['user7', 'user8', 'user9']
            };

            const author = context.payload.pull_request.user.login;
            const reviewers = [];
            for (const [group, members] of Object.entries(groups)) {
              // Pull Request 作成者はアサインから除く
              const filteredMembers = members.filter(user => user !== author);
              if (filteredMembers.length > 0) {
                const randomReviewer = filteredMembers[Math.floor(Math.random() * filteredMembers.length)];
                reviewers.push(randomReviewer);
              }
            }

            await github.rest.pulls.requestReviewers({
              owner: context.repo.owner,
              repo: context.repo.repo,
              pull_number: context.payload.pull_request.number,
              reviewers
            });

さいごに

actions/github-scriptoctokit/rest.js のドキュメントが分かりやすく、クライアントが素直に呼べるので直感的に書ける印象でした。
今回は対象のグループやメンバーを JavaScript 内で定義しましたが、別ファイルに切り出したり、CODEOWNERS から参照するなどが可能です。

この程度であれば shell でもそのまま書けますが、actions/github-script を使用することで記述が短く、shell が苦手でも JavaScript が書ければ改修できます。
また、要件が変わった時、shell に比べてロジックも修正しやすいだろうと判断して使用してみました。

参考

GitHub Actions でプルリクエストの自動アサインをする
PR の assignees が空だったときに自動アサイン
actions/github-script

GitHubで編集を提案

Discussion