# 通知設計書 30-上流ビルド原因

## 概要

本ドキュメントは、上流プロジェクトのビルドによってトリガーされたことを記録・通知する機能（UpstreamCause）の設計仕様を定義する。

### 本通知の処理概要

本通知は、BuildTriggerやReverseBuildTrigger等によってトリガーされたビルドに対して、どの上流ビルドがトリガー元であるかを記録し、ビルドログやUI上で表示する機能である。上流ビルドの連鎖を再帰的に記録することで、ビルドのトレーサビリティを提供する。

**業務上の目的・背景**：複雑なビルドパイプラインでは、あるビルドが失敗した場合にその原因を追跡する必要がある。UpstreamCauseは、ビルドがなぜトリガーされたかを記録し、上流ビルドへのリンクを提供することで、開発者やビルド管理者が問題の根本原因を迅速に特定できるようにする。

**通知の送信タイミング**：上流ビルドがスケジュールされた際に、CauseActionとしてビルドキューに追加される。ビルド開始時にビルドログに出力される。

**通知の受信者**：ビルドUI（ビルド詳細ページ）およびビルドログを閲覧するユーザー。

**通知内容の概要**：上流プロジェクト名、ビルド番号、および上流ビルドの原因（再帰的）が記録される。

**期待されるアクション**：ユーザーはリンクをクリックして上流ビルドを確認し、ビルドチェーンを追跡できる。

## 通知種別

ビルド原因通知（メタデータ記録・UI表示）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（ビルドスケジュール時に設定） |
| 優先度 | - |
| リトライ | 無し |

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

1. BuildTrigger/ReverseBuildTrigger等がscheduleBuild2()を呼び出す際にUpstreamCauseを生成
2. UpstreamCauseのコンストラクタで上流ビルドの情報を取得
3. 上流ビルドのCauseを再帰的にコピー（深さ・件数制限あり）

## 通知テンプレート

### ビルドログ出力

```
Started by upstream project "{upstreamProject}" build number {upstreamBuild}
originally caused by:
  {nestedCauses}
```

### ビルドUI表示

| 項目 | 内容 |
|------|------|
| 短い説明 | Started by upstream project "{upstreamProject}" build number {upstreamBuild} |
| リンク | 上流プロジェクトおよびビルドへのハイパーリンク |

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| upstreamProject | 上流プロジェクトのフルネーム | Run.getParent().getFullName() | Yes |
| upstreamBuild | 上流ビルド番号 | Run.getNumber() | Yes |
| upstreamUrl | 上流プロジェクトのURL | Run.getParent().getUrl() | Yes |
| upstreamCauses | 上流ビルドの原因（再帰） | Run.getCauses() | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| ビルドスケジュール | scheduleBuild2呼び出し | 上流ビルドから呼び出し | CauseActionとして追加 |

### 送信抑止条件

該当なし（上流ビルドからトリガーされた場合は常に記録）

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[上流ビルド完了] --> B[scheduleBuild2呼び出し]
    B --> C[UpstreamCause生成]
    C --> D[上流ビルド情報取得]
    D --> E[上流Causeを再帰取得]
    E --> F{深さ/件数制限?}
    F -->|Yes| G[DeeplyNestedUpstreamCause追加]
    F -->|No| H[Causeをtrim]
    G --> I[CauseAction設定]
    H --> I
    I --> J[ビルドキュー投入]
    J --> K[ビルド開始時にログ出力]
```

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

### 参照テーブル一覧

該当なし（メモリ上のオブジェクトとXML永続化）

### 参照データ

| データ | 内容 |
|--------|------|
| Run | 上流ビルドの情報 |
| Job | 上流プロジェクトの情報 |

### 更新対象

| 対象 | 操作 | 概要 |
|------|------|------|
| build.xml | INSERT | ビルド設定ファイルにCause情報を永続化 |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 上流プロジェクト削除 | 上流プロジェクトが存在しない | getUpstreamRun()がnullを返す |
| 循環参照 | 上流Causeに循環がある | traversedセットで検出、スキップ |
| 深さ超過 | MAX_DEPTH(10)を超える | DeeplyNestedUpstreamCause追加 |
| 件数超過 | MAX_LEAF(25)を超える | DeeplyNestedUpstreamCause追加 |

### リトライ仕様

該当なし

## 配信設定

### レート制限

該当なし

### 配信時間帯

該当なし

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

- 上流ビルドへのリンクはItem.READ権限がある場合のみ表示
- 上流プロジェクト/ビルドのフルネームはログに記録されるため、プロジェクト名の情報漏洩に注意

## 備考

- Causeクラスのスタティック内部クラスとして実装
- XStream2.PassthruConverterで古いデータ形式からの移行をサポート
- DeeplyNestedUpstreamCauseで深くネストした原因を省略表示
- @Exportedアノテーションで REST API からアクセス可能

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Cause.java | `core/src/main/java/hudson/model/Cause.java` | UpstreamCauseフィールド定義（157-169行目） |

**読解のコツ**: upstreamProject、upstreamBuild、upstreamUrl、upstreamCausesの4フィールドが核となるデータ。

#### Step 2: コンストラクタを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Cause.java | `core/src/main/java/hudson/model/Cause.java` | UpstreamCause(Run)コンストラクタ（180-193行目） |

**主要処理フロー**:
1. **181-183行目**: 上流ビルドの基本情報を取得
2. **184-192行目**: 上流ビルドのCauseを再帰的にコピー

#### Step 3: 再帰トリミングを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Cause.java | `core/src/main/java/hudson/model/Cause.java` | trim()メソッド（242-260行目） |

**主要処理フロー**:
1. **243-245行目**: UpstreamCause以外はそのまま返す
2. **248-255行目**: 深さ/件数制限をチェックし、必要に応じてDeeplyNestedUpstreamCause追加
3. **259行目**: 新しいUpstreamCauseを生成

#### Step 4: 出力処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Cause.java | `core/src/main/java/hudson/model/Cause.java` | print()メソッド（319-338行目） |

**主要処理フロー**:
- **321-325行目**: ModelHyperlinkNoteでリンク付きメッセージを出力
- **326-337行目**: ネストしたCauseを再帰的に出力

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

```
BuildTrigger / ReverseBuildTrigger
    │
    └─ scheduleBuild2(quietPeriod, new UpstreamCause(run))
           │
           └─ UpstreamCause(Run)
                  │
                  ├─ getNumber()
                  ├─ getParent().getFullName()
                  ├─ getParent().getUrl()
                  │
                  └─ getCauses()
                         │
                         └─ trim(cause, MAX_DEPTH, traversed)
                                │
                                ├─ 深さ/件数チェック
                                └─ DeeplyNestedUpstreamCause or 再帰
```

### データフロー図

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

上流Run ─────────────▶ UpstreamCause() ──┐
                             │            │
                      getCauses() ────────┼─▶ upstreamCauses
                             │            │
                         trim() ──────────┤
                             │            │
                      traversed Set ──────┘
                             │
                             ▼
                   MAX_DEPTH / MAX_LEAF チェック
                             │
                             ▼
                   CauseAction → ビルドキュー
                             │
                             ▼
                      print() → ビルドログ
                             │
                             ▼
               description.jelly → UI表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Cause.java | `core/src/main/java/hudson/model/Cause.java` | ソース | UpstreamCause実装 |
| CauseAction.java | `core/src/main/java/hudson/model/CauseAction.java` | ソース | Causeをビルドに関連付け |
| BuildTrigger.java | `core/src/main/java/hudson/tasks/BuildTrigger.java` | ソース | UpstreamCauseの生成元 |
| ReverseBuildTrigger.java | `core/src/main/java/jenkins/triggers/ReverseBuildTrigger.java` | ソース | UpstreamCauseの生成元 |
| description.jelly | `core/src/main/resources/hudson/model/Cause/UpstreamCause/description.jelly` | テンプレート | UI表示 |
| CauseTest.java | `test/src/test/java/hudson/model/CauseTest.java` | テスト | 単体テスト |
