# 通知設計書 27-上流プロジェクトビルドトリガー

## 概要

本ドキュメントは、上流プロジェクトのビルド完了後に自動的にビルドをトリガーする機能（ReverseBuildTrigger）の設計仕様を定義する。BuildTriggerとは逆に、下流プロジェクト側で上流プロジェクトを指定する方式である。

### 本通知の処理概要

本通知は、下流プロジェクト側で監視する上流プロジェクトを指定し、上流プロジェクトのビルドが完了した際に自動的にビルドをトリガーする機能である。BuildTriggerが上流側で下流を指定するのに対し、ReverseBuildTriggerは下流側で上流を指定する「逆向き」の依存関係定義を可能にする。

**業務上の目的・背景**：BuildTriggerでは上流プロジェクトの設定変更が必要だが、上流プロジェクトの設定を変更する権限がない場合や、上流プロジェクトの管理者と調整が必要な場合がある。ReverseBuildTriggerを使用すると、下流プロジェクトの管理者が独立して依存関係を設定できるため、組織間の調整を減らし、チームの自律性を高められる。

**通知の送信タイミング**：上流プロジェクトのビルド完了時に、ビルド結果が設定された閾値以上の場合にトリガーされる。AbstractProject同士の場合はDependencyGraph経由、それ以外はRunListener経由で処理される。

**通知の受信者**：下流プロジェクトのビルドキューに対してトリガーが送信される。

**通知内容の概要**：ビルドキューへの投入とUpstreamCauseの設定。

**期待されるアクション**：下流プロジェクト（自分自身）のビルドが自動的に開始される。

## 通知種別

ビルドトリガー（システム内イベント通知）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 非同期（上流ビルド完了後にキューに投入） |
| 優先度 | 中（quietPeriod適用） |
| リトライ | 無し |

### 送信先決定ロジック

1. ReverseBuildTriggerの設定でupstreamProjects（カンマ区切り）を解析
2. RunListener経由で上流ビルドの完了を監視
3. 上流ビルドの結果がthreshold以上の場合にトリガー

## 通知テンプレート

### ビルドログ出力

| 項目 | 内容 |
|-----|------|
| トリガー成功 | Triggering {project} #{buildNumber} |
| 既にキュー内 | {project} #{buildNumber} is already in the queue |
| 権限不足 | {runningAs} cannot even see {upstream} for trigger from {downstream} |
| 無効化中 | {project} is disabled |

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| upstreamProjects | 上流プロジェクト名（カンマ区切り） | 設定値 | Yes |
| threshold | トリガー条件となるビルド結果 | 設定値（デフォルトSUCCESS） | No |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| RunListener.onCompleted | 上流ビルド完了 | 結果が閾値以上 | 非AbstractProject用 |
| DependencyGraph | 上流ビルド完了 | 結果が閾値以上 | AbstractProject用 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| ビルド結果が閾値未満 | 設定された閾値を満たさない |
| 下流プロジェクトが無効化されている | isBuildable()がfalse |
| 権限不足 | 下流プロジェクトの認証で上流を参照できない |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[上流ビルド完了] --> B{AbstractProject?}
    B -->|Yes| C[DependencyGraph経由]
    B -->|No| D[RunListener経由]
    C --> E[shouldTrigger]
    D --> F[キャッシュから対象取得]
    F --> G[shouldTrigger]
    E --> H{shouldTrigger = true?}
    G --> H
    H -->|No| I[スキップ]
    H -->|Yes| J{isBuildable?}
    J -->|No| K[無効化ログ]
    J -->|Yes| L[scheduleBuild2]
    L --> M[UpstreamCause設定]
```

## データベース参照・更新仕様

### 参照テーブル一覧

該当なし（メモリ上のキャッシュとDependencyGraphを使用）

### 参照データ

| データ | 内容 |
|--------|------|
| upstream2Trigger | 上流プロジェクトからReverseBuildTriggerへのマッピングキャッシュ |
| DependencyGraph | プロジェクト間の依存関係グラフ |

### 更新対象

| 対象 | 操作 | 概要 |
|------|------|------|
| ビルドキュー | INSERT | 下流プロジェクトのビルドを投入 |
| CauseAction | INSERT | UpstreamCauseを設定 |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 上流プロジェクト未存在 | 上流プロジェクトが削除されている | ログ出力、スキップ |
| 権限不足 | 上流プロジェクトを参照できない | ログ出力、スキップ |
| 無効化 | 下流プロジェクトが無効化されている | ログ出力、スキップ |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0 |
| リトライ間隔 | - |
| リトライ対象エラー | - |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 制限なし |
| 1日あたり上限 | 制限なし |

### 配信時間帯

制限なし（上流ビルド完了時に即座に実行）

## セキュリティ考慮事項

- 下流プロジェクトの認証コンテキストで上流プロジェクトを参照
- Tasks.getAuthenticationOf2()で認証情報を取得
- 上流プロジェクトへのItem.READ権限が必要
- フォルダリネーム時に自動的にupstreamProjectsが更新される

## 備考

- 対となる機能はBuildTrigger（上流側で下流を指定）
- DependencyDeclarerインターフェースを実装
- @Symbolで"upstream"として参照可能
- Trigger<Job>を継承したトリガーとして実装
- RunListenerImplでキャッシュを管理し、パフォーマンスを最適化

---

## コードリーディングガイド

本通知を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ReverseBuildTrigger.java | `core/src/main/java/jenkins/triggers/ReverseBuildTrigger.java` | フィールド定義（90-92行目） |

**読解のコツ**: upstreamProjectsはカンマ区切りの文字列、thresholdはResult型でデフォルトSUCCESS。

#### Step 2: トリガー判定ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ReverseBuildTrigger.java | `core/src/main/java/jenkins/triggers/ReverseBuildTrigger.java` | shouldTrigger()メソッド（128-170行目） |

**主要処理フロー**:
1. **138-143行目**: 下流プロジェクトの可視性チェック
2. **145-156行目**: 下流プロジェクトの認証で上流を参照できるかチェック
3. **168-169行目**: ビルド結果と閾値を比較

#### Step 3: RunListener経由の処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ReverseBuildTrigger.java | `core/src/main/java/jenkins/triggers/ReverseBuildTrigger.java` | RunListenerImpl内部クラス（235-302行目） |

**主要処理フロー**:
1. **247-269行目**: calculateCache()でupstream2Triggerマップを構築
2. **272-301行目**: onCompleted()で上流ビルド完了時に処理

#### Step 4: DependencyGraph経由の処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | ReverseBuildTrigger.java | `core/src/main/java/jenkins/triggers/ReverseBuildTrigger.java` | buildDependencyGraph()メソッド（172-180行目） |

### プログラム呼び出し階層図

```
上流プロジェクトのビルド完了
    │
    ├─ AbstractProject同士の場合
    │      └─ DependencyGraph経由
    │             └─ buildDependencyGraph()
    │                    └─ shouldTriggerBuild()
    │                           └─ shouldTrigger()
    │
    └─ 非AbstractProjectの場合
           └─ RunListenerImpl.onCompleted()
                  │
                  ├─ upstream2Triggerキャッシュ参照
                  │      └─ calculateCache()（キャッシュ未構築時）
                  │
                  └─ shouldTrigger()
                         │
                         ├─ 可視性チェック
                         ├─ 権限チェック
                         └─ 閾値チェック
                                │
                                └─ scheduleBuild2(UpstreamCause)
```

### データフロー図

```
[入力]                    [処理]                        [出力]

upstreamProjects ───▶ Items.fromNameList() ──┐
                                              │
                     calculateCache() ────────┼─▶ upstream2Trigger
                                              │         │
上流ビルド完了 ──────────────────────────────────┼─────────▼
                                              │  onCompleted()
                                              │         │
threshold ────────────────────────────────────┘         ▼
                                                 shouldTrigger()
                                                        │
                                                        ▼
                                                scheduleBuild2()
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ReverseBuildTrigger.java | `core/src/main/java/jenkins/triggers/ReverseBuildTrigger.java` | ソース | メイントリガー実装 |
| BuildTrigger.java | `core/src/main/java/hudson/tasks/BuildTrigger.java` | ソース | 対となるトリガー |
| Cause.java | `core/src/main/java/hudson/model/Cause.java` | ソース | UpstreamCause定義 |
| ReverseBuildTriggerTest.java | `test/src/test/java/jenkins/triggers/ReverseBuildTriggerTest.java` | テスト | 単体テスト |
| config.jelly | `core/src/main/resources/jenkins/triggers/ReverseBuildTrigger/config.jelly` | テンプレート | UI設定画面 |
