# 画面設計書 68-プロジェクト関係図

## 概要

本ドキュメントは、Jenkins CI/CDサーバーの「プロジェクト関係図」画面の設計書です。

### 本画面の処理概要

2つのジョブ（プロジェクト）間のフィンガープリントに基づく依存関係を表示する画面です。上流プロジェクトと下流プロジェクトを比較し、ビルド間の関係を可視化します。

**業務上の目的・背景**：複雑なCI/CDパイプラインでは、複数のジョブが相互に依存関係を持ちます。この画面は、上流ジョブのビルドがどの下流ジョブのビルドに影響を与えているかを、フィンガープリント（ファイルの追跡情報）に基づいて可視化します。これにより、特定のビルドがどのビルドで使用されたかを追跡でき、障害分析やリリース管理に役立ちます。

**画面へのアクセス方法**：Jenkins管理画面のサイドパネルから「プロジェクト関係」リンクでアクセス、またはURLパス `/projectRelationship` から直接アクセスします。

**主要な操作・処理内容**：
1. 上流プロジェクト（upstream project）の選択
2. 下流プロジェクト（downstream project）の選択
3. 「Compare」ボタンで関係を比較
4. ビルド間の対応関係を表形式で表示

**画面遷移**：ダッシュボード/管理画面から遷移、各ビルドリンクからビルド詳細画面へ

**権限による表示制御**：選択したジョブへのREAD権限が必要です。権限がないジョブは選択できません。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 4 | ジョブ（Job） | 主機能 | ジョブ間の依存関係図表示 |
| 20 | ビルドトリガー | 補助機能 | 上流/下流プロジェクトの関係表示 |
| 19 | フィンガープリント | 補助機能 | ビルド間の関係算出 |

## 画面種別

検索 / 比較

## URL/ルーティング

- URL: `/projectRelationship`
- ルーティング: `Jenkins` クラスの Stapler バインディングにより URLにマッピングされます

## 入出力項目

| 項目名 | 入出力 | 型 | 必須 | 説明 |
|--------|--------|-----|------|------|
| lhs | 入力 | String | Yes | 上流プロジェクト（左側）のジョブ名 |
| rhs | 入力 | String | Yes | 下流プロジェクト（右側）のジョブ名 |

## 表示項目

| 項目名 | 型 | 説明 |
|--------|-----|------|
| Project Relationship | 見出し | 画面タイトル |
| body | テキスト | 機能の説明文 |
| upstream project | コンボボックス | 上流プロジェクト選択 |
| downstream project | コンボボックス | 下流プロジェクト選択 |
| Compare | ボタン | 比較実行ボタン |
| 関係テーブル | テーブル | ビルド対応関係の表示 |

### 関係テーブル詳細

| カラム | 型 | 説明 |
|--------|-----|------|
| 上流ビルド | リンク | 上流プロジェクトのビルドへのリンク |
| 下流ビルド範囲 | リンク群 | 下流プロジェクトの対応するビルド範囲 |

## イベント仕様

### 1-Compareボタン押下

2つのプロジェクトを選択して比較を実行します。

**URL**: `projectRelationship?lhs={job1}&rhs={job2}` (GET)

**処理フロー**：
1. GETパラメータからlhs（上流）とrhs（下流）のジョブ名を取得
2. 両方のジョブ名が指定されているか確認
3. `app.getItemByFullName()` で各ジョブを取得
4. ジョブが見つからない場合はエラーメッセージを表示
5. `jl.getRelationship(jr)` でフィンガープリントに基づく関係を算出
6. 関係が見つからない場合はエラーメッセージを表示
7. 関係テーブルを表示

### 2-コンボボックス入力

ジョブ名のオートコンプリート機能です。

**URL**: `fillJobNameItems` (AJAX)

**処理フロー**：
1. 入力文字列に基づいてジョブ名候補を検索
2. ユーザーがアクセス可能なジョブのみをフィルタリング
3. 候補リストを返却

## データベース更新仕様

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 比較実行 | なし | SELECT | フィンガープリントデータから関係を算出 |

### データ取得元

フィンガープリント情報を基に関係を算出します。

| データソース | 説明 |
|-------------|------|
| `$JENKINS_HOME/fingerprints/` | フィンガープリントXMLファイル群 |
| Job.getRelationship() | ジョブ間の関係算出メソッド |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|--------------|---------|
| Project Relationship | 見出し | Project Relationship | 常時表示 |
| body | 説明 | 機能説明文 | 常時表示 |
| upstream project | ラベル | upstream project | 常時表示 |
| downstream project | ラベル | downstream project | 常時表示 |
| Compare | ボタン | Compare | 常時表示 |
| - | エラー | No such project '{name}' | プロジェクトが見つからない場合 |
| - | エラー | There are no fingerprint records... | 関係が見つからない場合 |

## 例外処理

| 例外条件 | 対応 | 表示内容 |
|---------|------|---------|
| 上流プロジェクトが見つからない | エラーメッセージ | "No such project '{name}'" |
| 下流プロジェクトが見つからない | エラーメッセージ | "No such project '{name}'" |
| フィンガープリント関係なし | エラーメッセージ | "There are no fingerprint records that connect these two projects." |
| ジョブへの権限なし | 非表示/エラー | コンボボックスに候補が表示されない |

## 備考

- フィンガープリントが記録されていないビルドは関係図に表示されません
- 関係は上流から下流への方向性を持ちます
- MavenプロジェクトやPipelineでは自動的にフィンガープリントが記録される場合があります
- 手動でフィンガープリントを記録するには、ビルドステップでFingerprint機能を使用します
- コンボボックスは `f:combobox` タグでオートコンプリート対応しています

---

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

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

### 推奨読解順序

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

まず、ジョブ間の関係算出の仕組みを理解します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Job.java | `core/src/main/java/hudson/model/Job.java` | getRelationship()メソッドを検索して理解 |
| 1-2 | Fingerprint.java | `core/src/main/java/hudson/model/Fingerprint.java` | RangeSetによるビルド範囲の管理を理解 |

**読解のコツ**: `getRelationship()` メソッドはフィンガープリントを走査して、上流ビルドと下流ビルドの対応関係を`Map<Integer, RangeSet>`として返します。

#### Step 2: エントリーポイントを理解する

画面表示の起点となるファイルを特定します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | projectRelationship.jelly | `core/src/main/resources/jenkins/model/Jenkins/projectRelationship.jelly` | 画面構造、フォーム、条件分岐、テーブル表示を理解 |

**主要処理フロー**:
1. **行31**: レイアウトとタイトルの設定
2. **行32-33**: サイドパネルとパンくずリスト
3. **行35-38**: app-barとヘルプリンク
4. **行40-42**: 説明文
5. **行44-54**: フォーム（GETメソッド）
6. **行45-48**: 上流プロジェクトのコンボボックス
7. **行50-53**: 下流プロジェクトのコンボボックス
8. **行56-89**: 条件分岐（lhs/rhsが指定されている場合）

#### Step 3: 関係テーブル表示を理解する

関係データの表示処理を理解します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | projectRelationship.jelly (後半) | 同上 | j:forEach、t:buildLink、t:buildRangeLinkの使い方を理解 |

**主要処理フロー**:
- **行57-58**: `app.getItemByFullName()` でジョブ取得
- **行60-66**: ジョブが見つからない場合のエラー表示
- **行67-88**: 関係テーブル表示
- **行69**: `jl.getRelationship(jr)` で関係算出
- **行73-85**: ビルドリンクとビルド範囲リンクの表示

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

```
projectRelationship.jelly (画面表示)
    │
    ├─ <f:form action="projectRelationship" method="get">
    │      │
    │      ├─ f:combobox (lhs) ─── fillUrl="fillJobNameItems"
    │      │
    │      └─ f:combobox (rhs) ─── fillUrl="fillJobNameItems"
    │
    ├─ j:if lhs & rhs are specified
    │      │
    │      ├─ app.getItemByFullName(lhs) → jl
    │      │
    │      ├─ app.getItemByFullName(rhs) → jr
    │      │
    │      ├─ jl == null → error "No such project"
    │      │
    │      ├─ jr == null → error "No such project"
    │      │
    │      └─ jl.getRelationship(jr) → relation
    │             │
    │             ├─ empty(relation) → error "No fingerprint records"
    │             │
    │             └─ j:forEach e in relation
    │                    │
    │                    ├─ t:buildLink job="${jl}" number="${e.key}"
    │                    │
    │                    └─ t:buildRangeLink job="${jr}" range="${e.value}"

fillJobNameItems (AJAX)
    │
    └─ Jenkins.doFillJobNameItems()
           │
           └─ 権限フィルタリング済みジョブ名リスト
```

### データフロー図

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

lhs(上流ジョブ名) ────▶ getItemByFullName(lhs) ────▶ Job jl
                              │
                              ▼
rhs(下流ジョブ名) ────▶ getItemByFullName(rhs) ────▶ Job jr
                              │
                              ▼
                    jl.getRelationship(jr)
                              │
                              ├─ Fingerprintを走査
                              │
                              ├─ 両方のジョブで使用されたファイルを検索
                              │
                              └─ Map<Integer, RangeSet>
                                    │
                                    │  key: 上流ビルド番号
                                    │  value: 下流ビルド番号範囲
                                    │
                                    ▼
                              関係テーブル表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| projectRelationship.jelly | `core/src/main/resources/jenkins/model/Jenkins/projectRelationship.jelly` | テンプレート | 画面表示用Jellyテンプレート |
| Jenkins.java | `core/src/main/java/jenkins/model/Jenkins.java` | ソース | fillJobNameItems()を含む |
| Job.java | `core/src/main/java/hudson/model/Job.java` | ソース | getRelationship()を含む |
| Fingerprint.java | `core/src/main/java/hudson/model/Fingerprint.java` | ソース | RangeSetデータ構造 |
| buildLink.jelly | `core/src/main/resources/lib/hudson/buildLink.jelly` | テンプレート | ビルドリンク生成タグ |
| buildRangeLink.jelly | `core/src/main/resources/lib/hudson/buildRangeLink.jelly` | テンプレート | ビルド範囲リンク生成タグ |
| combobox.jelly | `core/src/main/resources/lib/form/combobox.jelly` | テンプレート | オートコンプリート付きコンボボックス |
