📘

【GtiHub Actions】PR 作成時に作成者を自動アサインする【詳解】

2024/12/18に公開

はじめに

毎回 PR の assignees に自分を割り当てるのが面倒だったため、自動化しました。GitHub Actions で実現する方法を書いています。

後半では使用した GitHub Actions の API の解説を書いています。英語の記事を読むに当たり、よしなに DeepL や LLM を使用しています。

assignees に自動アサインする方法の調査

主に以下の方法がありそうでした。

  1. GitHub Actions でワークフローを作成 (本記事の内容)
  2. GtiHub Actions の公開 Action を利用 (assign-author)
  3. GitHub Bot を利用 (auto-assign)

今回は1を採用しました。今回のワークフローの単純さから、外部ライブラリを使用する学習コストよりも、ワークフローのメンテナンス・コストの方が低いと感じたためです。

コード

PR の assignees に作成者を自動アサインする GitHub Actions のコードは、以下のとおりです。

name: Auto PR Assign

on:
  pull_request:
    types: ["opened"]

permissions:
  pull-requests: write
  repository-projects: read

jobs:
  assign:
    # ボットが作成した PR をスキップする
    if: endsWith(github.actor, '[bot]') == false
    runs-on: ubuntu-latest
    timeout-minutes: 1
    steps:
      - name: Add event actor to assignees
        run: gh pr edit ${{ github.event.number }} --add-assignee ${{ github.actor }}
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          GH_REPO: ${{ github.repository }}

GITHUB_TOKEN の割り当て方法

他の記事では以下の割り当て方をよく見かけました。

GH_TOKEN: ${{ github.token }}

自動トークン認証 の内容に合わせ、以下のように変更しています。

GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

既にアサインされているかの判定

他の記事では以下の判定をよく見ましたが、排除しました。on.pull_request.typesopenned を指定しており、PR 作成時にすでにアサインされているような状況がないと考えたためです。

    if: github.event.pull_request.assignee == null

もし間違っていればコメントをお願いします。

解説

筆者はあまり GitHub Actions に詳しくなく、この機会に調べてみました。基本的に公式ドキュメントを参照し、内容を要約しています。

on.pull_request

  • ワークフローの概要
    • ワークフローのリポジトリにあるプルリクエストのアクティビティが発生したときに、ワークフローを実行する
  • ワークフローのトリガー
    • デフォルトは open, synchronize, reopened の3つのアクティビティタイプ
    • ワークフローを起動するアクティビティタイプを変更するには、types キーワードを使う
  • マージ・コンフリクト
    • PR にマージ・コンフリクトがある場合、ワークフローは実行されない
      • マージ・コンフリクトは最初に解決されなければならない
    • しかし、pull_request_target イベントを持つワークフローは、PR にマージ・コンフリクトがあっても実行される

on.pull_request.types

pull_request の項目の、Activity types にある値を指定できる。

以下に代表的なものを列挙する。

タイプ 説明
assigned ユーザーがプルリクエストに割り当てられる
unassigned ユーザーがプルリクエストから解除される
labeled ラベルがプルリクエストに適用される
unlabeled ラベルがプルリクエストから削除される
opened プルリクエストが作成される
edited タイトル、本文、またはベースブランチが変更される
closed プルリクエストが閉じられる(マージされない場合)
reopened 閉じたプルリクエストが再度開かれる
synchronize コミットがプルリクエストにプッシュされる
ready_for_review プルリクエストが下書きモードから解除される
locked プルリクエストがロックされる
unlocked プルリクエストのロックが解除される
review_requested ユーザーにレビューをリクエストする
review_request_removed ユーザーからのレビューリクエストを削除する

permissions

  • パーミッション
    • GITHUB_TOKEN に付与されたデフォルトのパーミッションを変更できる
    • 必要に応じてアクセスを追加または削除することで、必要最小限のアクセスのみを許可することができる
  • スコープ
    • トップレベル・キー
      • ワークフロー内のすべてのジョブに適用する
    • ジョブ・キー
      • 特定のジョブに対してパーミッションを適用する
        • ジョブ内で GITHUB_TOKEN を使用するすべてのアクションおよび実行コマンドが、指定したアクセス権を獲得する
        • 詳細は jobs.<job_id>.permissions を参照
  • パーミッションの値
    • read(該当する場合), write, none のいずれかのアクセスレベルを割り当てることができる
  • パーミッションの種類
    • 以下の表を参照
    • これらのパーミッションのどれかにアクセスを指定すると、指定されていないパーミッションの値はすべて none に設定される
パーミッション 説明
actions GitHub Actionsのワークフローを操作します。例: actions: write でワークフローを作成、更新、削除できます。
checks チェックの操作を行います。例: GitHubのチェック API を使用してステータスチェックを生成します。
contents リポジトリのコンテンツ(ファイル)にアクセスします。例: ファイルの読み取り、作成、更新が可能です。
deployments デプロイメントの管理を行います。例: 環境へのデプロイを管理したり作成したりします。
discussions GitHub Discussions の操作を行います。例: ディスカッションの作成、変更が可能です。
issues GitHubのIssueの操作を行います。例: Issueを読み取り、コメント、または作成します。
packages GitHub Packagesを管理します。例: パッケージを公開またはインストールする操作が可能です。
pages GitHub Pages のコンテンツを管理します。例: ページのビルドとデプロイを行います。
pull-requests Pull Request の管理を行います。例: PRに対してコメントしたりラベルを追加したりします。
repository-projects GitHub プロジェクトの操作を行います。例: プロジェクトボードを読み取り、更新します。
security-events GitHubのセキュリティ関連イベントを操作します。例: Dependabotアラートへのアクセスを許可します。
statuses コミットに対するステータスの操作を行います。例: ステータスチェックを作成、更新します。

jobs

  • 構成
    • ワークフローの実行は 1 つ以上のジョブで構成される
  • 並列実行と直列実行
    • デフォルトではジョブは並行して実行される
    • ジョブを連続して実行するには、jobs.<job_id>.needs キーワードを使用する
      • 他のジョブへの依存関係を定義する
  • 実行環境
    • 各ジョブは、runs-on で指定された実行環境で実行される
  • ジョブの実行数・課金

jobs.<job_id>

  • ジョブ ID
    • ジョブに一意な識別子を付与する
    • キー job_id は文字列である
      • 文字または _ で始まる必要がある
      • 英数字, -, _ のみを使用できる

jobs.<job_id>.steps

  • ステップ
    • ジョブにはステップと呼ばれる一連のタスクが含まれる
    • ステップでは以下のようなことができる
      • コマンドを実行する
      • セットアップタスクを実行する
      • 自分のリポジトリや公開リポジトリ、Dockerレジストリで公開されているアクションを実行する
  • 実行プロセス
    • 各ステップは実行環境内の独自のプロセスで実行される
      • ワークスペースとファイルシステムにアクセスできる
      • ステップ間での環境変数の変更は保存されない
  • ビルドインステップ
    • GitHub には、ジョブのセットアップと完了のためのビルトインステップが用意されている
  • 表示制限
    • GitHub には最初の 1,000 個のチェックしか表示されない
    • ワークフローの使用量制限内であれば、ステップの数は無制限に実行できる

jobs.<job_id>.runs-on

  • runs-on
    • ジョブを実行するマシンの種類を定義する
  • マシンの種類
    • GitHubホストランナー
    • 大規模ランナー
    • セルフホストランナー
  • ランナーのターゲット方法
    • ランナーに割り当てられたラベル
    • グループメンバーシップ
    • 上記の組み合わせ
  • runs-on の有効な値
    • 文字列
    • 文字列を含む変数
    • 文字列の配列、文字列を含む変数、またはその両方の組み合わせ
    • group、または label キーを使った key: value ペア
  • 変数と文字列の混合
    • 以下のように、配列の中に変数と文字列を混ぜることができる
      • runs-on: [self-hosted, "${{ inputs.chosen-os }}"]
        • より詳細なサンプルは 元記事 のコードを参照
  • 配列の指定
    • ワークフローは指定された run-on の値の全てにマッチするランナー上で実行される
    • 例えば、以下の場合はジョブはlinux, x64, gpu のラベルを持つセルフホストランナーのみで実行される
      • runs-on: [self-hosted, linux, x64, gpu]
  • 複数マシンでの実行

jobs.<job_id>.steps[*].timeout-minutes

  • タイムアウト分数
    • プロセスを終了する前にステップを実行する最大分数
    • 値は正の整数である必要がある

jobs.<job_id>.steps[*].name

  • ステップ名
    • GitHub で表示するステップの名前

jobs.<job_id>.steps[*].run

  • run
    • コマンドライン・プログラムをオペレーティング・システムのシェルを使用して実行する
  • 上限値
    • 21,000文字
  • ステップ名
    • name を指定しない場合、ステップ名はデフォルトで run コマンドで指定されたテキストになる
  • シェルの変更
    • 別のシェルを選択し、コマンドの実行に使用するシェルをカスタマイズすることがきる
    • 詳細については、jobs.<job_id>.steps[*].shell を参照
  • 書き方
    • 単一行と複数行の書き方は以下を参照
# 単一行
- name: Install Dependencies
  run: npm install

# 複数行
- name: Clean install dependencies and build
  run: |
    npm ci
    npm run build

jobs.<job_id>.steps[*].env

  • ステップの変数
    • 実行環境で使用するステップの変数を設定する
    • ワークフロー全体やジョブに対して変数を設定することもできる
  • 変数名の重複と優先度
    • 複数の環境変数が同じ名前で定義されている場合、GitHub は最も具体的な変数を使用する
      • 例えば、あるステップで定義された環境変数は、そのステップが実行されている間、同じ名前のジョブやワークフローの環境変数を上書きする
      • ジョブに定義された環境変数は、ジョブが実行されている間、同名のワークフロー変数を上書きする
  • 公開アクションの変数へのアクセス
    • 公開アクションでは、READMEファイルで期待される変数を指定することができる
  • シークレット情報へのアクセス
steps:
  - name: My first action
    env:
      GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      FIRST_NAME: Mona
      LAST_NAME: Octocat

終わりに

どうやら、GitHub Actions のトリガーには、 GitHub の Webhook イベントを利用しているようですね。ワークフローのトリガーとなるイベント には、冒頭に以下の記述がありました。

ワークフローのトリガーは、ワークフローを実行させるイベントです。イベントには複数のアクティビティタイプがあります。各アクティビティタイプの意味については、Webhook イベントとペイロード を参照してください。

また、最初は公式ドキュメントに出てくる README file のことがよくわかりませんでした。調べたところ、カスタムアクションについて の内容が該当しそうでした。

  • README.md ファイル
    • アクションの使用方法を伝えるため、README ファイルを作成することをお勧めする
    • README.md には、以下の情報を含めることができる
      • アクションが実行する内容の説明
      • 必須の入力引数と出力引数
      • オプションの入力引数と出力引数
      • アクションが使用するシークレット
      • アクションが使用する環境変数
      • ワークフローにおけるアクションの使用例

これは公開するアクションの製作者向けですかね。

「GitHub Actions わからん」から「GitHub Actions 完全に理解した(理解していない)」まで進化できました。どこかで、GitHub Actions の基本についてまとめた記事も書きたいですね。

以上、GitHub Actions で PR の assignees に自動アサインする方法と、実現において使用した GitHub Actions の API の解説でした。

参考文献

Discussion