# バッチ設計書 4-PrAssignee

## 概要

本ドキュメントは、JuliaLangリポジトリにおけるPR Assignee GitHub Actionsワークフローのバッチ設計書である。PR作成時に外部コントリビューターのPRへランダムにコミッターをレビュアーとして自動アサインするCI/CDパイプラインの一部として機能する。

### 本バッチの処理概要

このバッチは、プルリクエストの作成・再オープン・ドラフト解除時に自動実行され、外部コントリビューター（リポジトリへの書き込み権限を持たないユーザー）のPRに対して、JuliaLangコミッターからランダムに1名をアサイニーとして設定するワークフローである。

**業務上の目的・背景**：Juliaプロジェクトは多くの外部コントリビューターからPRを受け付けている。外部コントリビューターのPRが長期間レビュアー不在のまま放置されることを防ぐため、PR作成時にコミッターを自動的にアサインし、レビュー責任者を明確にすることで、PRレビュープロセスの迅速化とコントリビューター体験の向上を図る。

**バッチの実行タイミング**：`pull_request_target`イベント（opened, reopened, ready_for_review）発生時に自動実行される。ドラフトPRの場合はスキップされる。

**主要な処理内容**：
1. PR作成者がリポジトリのコラボレーター（push/maintain/admin権限）かどうかを判定
2. コラボレーターの場合はスキップ（BumpStdlibs.jlBot、dependabotも除外）
3. 既にアサイニーがいる場合はスキップ
4. JuliaLang/pr-assignmentリポジトリのusers.txtからアサイニー候補リストを取得
5. 候補リストからランダムに1名を選出し、PRのアサイニーとして設定
6. 設定結果を検証し、失敗した場合はエラーをスローする

**前後の処理との関連**：本バッチは独立したCIジョブであるが、No.3 LabelCheckとともにPR管理プロセスの一環として機能する。アサイニー候補リストはJuliaLang/pr-assignmentリポジトリで管理されている。

**影響範囲**：外部コントリビューターが作成した非ドラフトのPRが対象。PRのアサイニーフィールドが変更される。pull_request_targetイベントを使用しているため、GITHUB_TOKENに書き込み権限があり、セキュリティ上の注意が必要（PRのソースコードをチェックアウトしてはならない）。

## バッチ種別

自動化処理（PRワークフロー管理）

## 実行スケジュール

| 項目 | 内容 |
|-----|------|
| 実行頻度 | イベント駆動（随時） |
| 実行時刻 | N/A |
| 実行曜日 | N/A |
| 実行日 | N/A |
| トリガー | GitHub Actionsイベント（pull_request_target: opened, reopened, ready_for_review） |

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| GitHubリポジトリ | JuliaLang/juliaリポジトリ上で動作すること |
| ランナー環境 | ubuntu-latestが利用可能であること |
| GITHUB_TOKEN | pull-requests: write権限を持つトークン |
| pr-assignmentリポジトリ | JuliaLang/pr-assignmentリポジトリのusers.txtが存在すること |

### 実行可否判定

以下の条件を全て満たす場合にアサイニー設定が実行される：
- PRがドラフトでないこと（`github.event.pull_request.draft != true`）
- PRに既存のアサイニーがいないこと
- PR作成者がリポジトリのコラボレーター（push/maintain/admin権限）でないこと
- ただしActions Runner Debugモードが有効な場合はコラボレーターのPRでも実行される

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | デフォルト値 | 説明 |
|-------------|-----|-----|-------------|------|
| context.payload.pull_request | Object | Yes | - | PRの情報（GitHubが自動提供） |
| RUNNER_DEBUG | String | No | undefined | Actions Runnerデバッグモードフラグ |

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| PRメタデータ | GitHub API | PRの作成者、アサイニー、ドラフト状態 |
| コラボレーターリスト | GitHub API | リポジトリのコラボレーター一覧（push/maintain/admin権限） |
| users.txt | テキスト | JuliaLang/pr-assignment/main/users.txtからのアサイニー候補リスト |

## 出力仕様

### 出力データ

| 出力先 | 形式 | 説明 |
|-------|------|------|
| GitHub PR | API操作 | PRのアサイニーフィールドへの設定 |
| GitHub Actions Log | テキスト | 処理の各ステップのログ出力 |

### 出力ファイル仕様

| 項目 | 内容 |
|-----|------|
| ファイル名 | N/A（ファイル出力なし） |
| 出力先 | GitHub Actions実行ログ |
| 文字コード | N/A |
| 区切り文字 | N/A |

## 処理フロー

### 処理シーケンス

```
1. PRイベント受信
   └─ pull_request_target (opened/reopened/ready_for_review)
2. ドラフトPRチェック
   └─ ドラフトの場合はジョブ全体をスキップ
3. 既存アサイニーチェック
   └─ 既にアサイニーがいる場合はスキップ（return）
4. コラボレーター判定
   ├─ push/maintain/admin権限を持つコラボレーター一覧を取得（ページネーション対応）
   ├─ BumpStdlibs.jlBot（DilumAluthgeBot）とdependabotをリストに追加
   └─ PR作成者がリスト内にいればコラボレーターと判定
5. コラボレーターの場合
   ├─ RUNNER_DEBUG=trueの場合は処理を継続
   └─ それ以外はスキップ（return）
6. アサイニー候補取得
   ├─ JuliaLang/pr-assignment/main/users.txtをGitHub API経由で取得
   ├─ Base64デコードしてテキストに変換
   └─ 正規表現 /^@([a-zA-Z0-9\-]+)/ でユーザー名を抽出
7. ランダムアサイン
   ├─ 候補リストからランダムに1名を選出
   └─ github.rest.issues.addAssignees()でPRにアサイン
8. 結果検証
   ├─ github.rest.pulls.get()でPR情報を再取得
   ├─ アサイニーが正しく設定されたか確認
   └─ 失敗した場合はエラーをスロー
```

### フローチャート

```mermaid
flowchart TD
    A[pull_request_target イベント] --> B{ドラフトPR?}
    B -->|Yes| C[ジョブスキップ]
    B -->|No| D{既存アサイニーあり?}
    D -->|Yes| E[スキップ return]
    D -->|No| F[コラボレーター判定]
    F --> G{PR作成者はコラボレーター?}
    G -->|Yes| H{RUNNER_DEBUG?}
    H -->|true| I[処理継続]
    H -->|false| J[スキップ return]
    G -->|No| I
    I --> K[users.txt取得]
    K --> L[候補からランダム選出]
    L --> M[addAssigneesでアサイン]
    M --> N[結果検証]
    N --> O{アサイン成功?}
    O -->|Yes| P[正常終了]
    O -->|No| Q[エラースロー]
```

## データベース操作仕様

### 操作別データベース影響一覧

| 処理 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| N/A | N/A | N/A | データベース操作なし（GitHub API操作のみ） |

### テーブル別操作詳細

該当なし。本バッチはGitHub APIを使用してPRメタデータを操作する。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| Error | 候補なし | assigneeCandidatesが空の場合 | JuliaLang/pr-assignment/users.txtの内容を確認 |
| Error | アサイン失敗 | addAssigneesのAPI呼び出しが失敗した場合 | GitHubの一時的なエラーの場合は再実行 |
| 404 | コラボレーターAPI | PR作成者がコラボレーターの場合に発生（正常動作） | リトライ対象外（retry-exempt-status-codes: 404） |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 5回（actions/github-scriptの設定） |
| リトライ間隔 | 指数バックオフ |
| リトライ対象エラー | GitHub APIエラー（404を除く） |

### 障害時対応

ワークフロー失敗時は手動でPRのアサイニーを設定する。users.txtの内容が不正な場合はJuliaLang/pr-assignmentリポジトリを修正する。

## トランザクション仕様

| 項目 | 内容 |
|-----|------|
| トランザクション範囲 | N/A（GitHub API操作はトランザクション不可） |
| コミットタイミング | N/A |
| ロールバック条件 | N/A |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | 1件（対象PR） |
| 目標処理時間 | GitHub Actionsのデフォルトタイムアウト内 |
| メモリ使用量上限 | GitHub Actionsランナーの標準上限 |

## 排他制御

GitHub APIのアサイニー設定は冪等であるため、排他制御は不要。ただし、同一PRに対して複数のイベントが近接して発生した場合、最後に実行されたアサインが有効となる。

## ログ出力

| ログ種別 | 出力タイミング | 出力内容 |
|---------|--------------|---------|
| アサイニー情報 | 処理開始時 | oldPrAssignees: 既存アサイニーリスト |
| PR作成者情報 | コラボレーター判定時 | prAuthor, isCollaborator |
| 候補リスト | 候補取得後 | assigneeCandidates: 候補ユーザー名リスト |
| アサイン結果 | アサイン後 | selectedAssignee, 成功/失敗メッセージ |
| デバッグ情報 | デバッグモード時 | RUNNER_DEBUG, thisIsActionsRunnerDebugMode |

## 監視・アラート

| 監視項目 | 閾値 | アラート先 |
|---------|-----|----------|
| ワークフロー失敗 | 1回 | GitHub Actions実行ログ |

## 備考

- **セキュリティ上の重要な注意**：`pull_request_target`イベントを使用しているため、GITHUB_TOKENに書き込み権限がある。PRのソースコードをチェックアウトしてはならない（信頼されていないコード実行のリスク）
- actions/github-script@v8.0.0（コミットハッシュ固定：ed597411d8f924073f98dfc5c65a23a2325f34cd）を使用
- コミッターリストへの追加はJuliaLang/pr-assignmentリポジトリのusers.txtを編集することで行える
- PRラベルの自動付与機能（`status: waiting for PR reviewer`）はコメントアウトされており、現在は無効
- BumpStdlibs.jlBot（DilumAluthgeBot）とdependabotのPRは自動的にスキップされる
- permissionsはpull-requests: writeのみに設定されている
