# 通知設計書 16-プラグインラッパー警告（PluginWrapperAdministrativeMonitor）

## 概要

本ドキュメントは、Jenkins管理画面に表示される「プラグインラッパー警告」通知の設計仕様を定義する。この通知は、プラグインのロードに失敗した場合（依存関係の不足やバージョン不整合など）に管理者に警告を表示する。

### 本通知の処理概要

この通知は、Jenkinsの管理画面（/manage）において危険度の高い警告（danger）として表示される管理者モニター機能である。プラグインのロード処理中に発生した依存関係エラーを収集し、管理者に通知する。

**業務上の目的・背景**：プラグインの依存関係エラー（必要な依存プラグインの不足、バージョン不整合など）は、プラグインが正常に動作しない原因となる。この警告により、管理者は問題のあるプラグイン構成を認識し、必要なプラグインのインストールや更新を行える。

**通知の送信タイミング**：Jenkins管理画面（/manage）にアクセスした際に、依存関係エラーを持つプラグインが1つ以上存在する場合に表示される。エラー情報はJenkinsの起動時にプラグインのロード処理中に収集される。

**通知の受信者**：Jenkins管理者（ADMINISTER権限を持つユーザー）。管理画面にアクセスできるユーザーのみがこの警告を確認可能。

**通知内容の概要**：依存関係エラーを持つプラグインのリスト（プラグイン名、バージョン、エラー詳細）が表示される。直接的なエラーと、他のプラグインのエラーに起因する間接的なエラーが区別して表示される。

**期待されるアクション**：管理者は「Correct」ボタンをクリックしてプラグインマネージャーに移動し、不足しているプラグインのインストールや既存プラグインの更新を行う。

## 通知種別

アプリ内通知（Jenkins管理画面内のAdministrativeMonitor）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（画面レンダリング時に判定） |
| 優先度 | 高（プラグイン動作に関わる重大なエラー） |
| リトライ | 該当なし（画面表示のため） |

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

AdministrativeMonitorフレームワークにより、Jenkins管理画面（/manage）にアクセスした管理者権限を持つユーザーに対して自動的に表示される。

## 通知テンプレート

### 表示形式

| 項目 | 内容 |
|-----|------|
| 表示エリア | Jenkins管理画面上部の警告セクション |
| スタイル | jenkins-alert jenkins-alert-danger（赤色背景の危険スタイル） |
| 形式 | HTML（Jellyテンプレート） |

### 本文テンプレート

```html
<div class="jenkins-alert jenkins-alert-danger" role="alert">
    <form method="post" action="${rootURL}/${it.url}/act" name="${it.id}">
        <button name="correct">Correct</button>
    </form>
    <p>直接的な依存関係エラーの説明...</p>
    <p><strong>直接依存のあるプラグイン：</strong></p>
    <!-- 直接エラーを持つプラグイン -->
    <dl>
        <dt>プラグイン名 (バージョン)</dt>
        <dd>エラーメッセージ</dd>
    </dl>
    <!-- 間接エラーがある場合 -->
    <p>間接的な依存関係エラーの説明...</p>
    <p><strong>間接依存のあるプラグイン：</strong></p>
    <dl>
        <dt>プラグイン名 (バージョン)</dt>
        <dd>エラーメッセージ</dd>
    </dl>
</div>
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| it.url | モニターのURL | AdministrativeMonitor.getUrl() | Yes |
| it.id | モニターのID | AdministrativeMonitor.getId() | Yes |
| it.plugins | 問題のあるプラグインリスト | PluginWrapperAdministrativeMonitor.getPlugins() | Yes |
| plugin.longName | プラグインの正式名称 | PluginWrapper.getLongName() | Yes |
| plugin.version | プラグインのバージョン | PluginWrapper.getVersion() | Yes |
| plugin.originalDependencyErrors | 直接的な依存関係エラー | PluginWrapper.getOriginalDependencyErrors() | No |
| plugin.derivedDependencyErrors | 間接的な依存関係エラー | PluginWrapper.getDerivedDependencyErrors() | No |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| 画面操作 | /manage画面アクセス | plugins.size() > 0 | 依存関係エラーのあるプラグインが存在する場合 |
| システムイベント | プラグインロード失敗 | dependencyErrors非空 | Jenkins起動時のプラグインロードでエラー発生 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| エラープラグインなし | 全プラグインが正常にロードされた場合は非表示 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[Jenkins起動] --> B[プラグインロード処理]
    B --> C{依存関係解決}
    C -->|エラー| D[dependencyErrorsに追加]
    C -->|成功| E[正常ロード]
    D --> F[NOTICE.addPlugin呼び出し]
    F --> G[管理画面アクセス]
    E --> G
    G --> H[AdministrativeMonitor.all取得]
    H --> I[PluginWrapperAdministrativeMonitor.isActivated]
    I --> J{pluginsマップ<br>が空でない?}
    J -->|はい| K[警告メッセージ表示]
    J -->|いいえ| L[表示スキップ]
    K --> M{ユーザーアクション}
    M -->|Correct| N[プラグインマネージャーへリダイレクト]
    N --> O[終了]
    L --> O
```

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

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| 該当なし | - | メモリ上の状態を参照 |

### メモリ参照

#### PluginWrapperAdministrativeMonitor

| 参照項目 | 用途 | 取得条件 |
|-------------------|------|---------|
| plugins | 問題のあるプラグインマップ | Map<String, PluginWrapper> |

#### PluginWrapper

| 参照項目 | 用途 | 取得条件 |
|-------------------|------|---------|
| dependencyErrors | 依存関係エラーマップ | Map<String, Boolean> |
| originalDependencyErrors | 直接的なエラー | derived == false |
| derivedDependencyErrors | 間接的なエラー | derived == true |

### 更新処理

| 操作 | 対象 | 更新値 | 備考 |
|-----|-----------------|-------|------|
| PUT | plugins | PluginWrapper | PluginWrapper.resolvePluginDependencies()でエラー発生時 |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 依存プラグイン不足 | 必要なプラグインが未インストール | プラグインマネージャーでインストール |
| バージョン不整合 | 依存プラグインのバージョンが不足 | プラグインマネージャーで更新 |
| プラグイン無効 | 依存プラグインがdisabled | プラグインを有効化 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 該当なし（画面操作のため） |
| リトライ間隔 | 該当なし |
| リトライ対象エラー | 該当なし |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 制限なし（画面表示のため） |
| 1日あたり上限 | 制限なし |

### 配信時間帯

制限なし（管理画面アクセス時に常時判定）

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

- doActメソッドはPOSTリクエストのみ受け付ける
- 「Correct」アクションはプラグインマネージャーへのリダイレクトのみを行う
- プラグイン情報の表示には管理者権限が必要

## 備考

- このモニターはPluginWrapper内部クラスとして定義されている
- PluginWrapper.NOTICEフィールドとして静的にアクセス可能
- get()静的メソッドでシングルトンインスタンスを取得可能
- 直接エラー（original）と間接エラー（derived）を区別して表示
- 間接エラーは他のプラグインの失敗に起因するもの

---

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

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

### 推奨読解順序

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

まず、依存関係エラー情報の構造を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | PluginWrapper.java | `core/src/main/java/hudson/PluginWrapper.java` | dependencyErrorsフィールド（行202）とgetOriginalDependencyErrors/getDerivedDependencyErrorsメソッドを理解 |

**読解のコツ**: dependencyErrorsはMap<String, Boolean>で、Booleanがtrueの場合はderived（間接的）エラー、falseの場合はoriginal（直接的）エラーを示す。

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

処理の起点となるAdministrativeMonitorクラスを特定。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | PluginWrapper.java | `core/src/main/java/hudson/PluginWrapper.java` | PluginWrapperAdministrativeMonitor内部クラス（行1204-1253付近）を確認 |

**主要処理フロー**:
1. **行1205**: NOTICE静的フィールドとして定義
2. **行1210**: PluginWrapperAdministrativeMonitorクラス定義
3. **行1211**: pluginsマップでエラープラグインを保持
4. **行1213-1215**: addPlugin()でエラープラグインを登録
5. **行1217-1220**: isActivated()でエラープラグインの存在を確認
6. **行1243-1248**: doAct()で「Correct」ボタン押下時にプラグインマネージャーへリダイレクト

#### Step 3: UIテンプレートを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | message.jelly | `core/src/main/resources/hudson/PluginWrapper/PluginWrapperAdministrativeMonitor/message.jelly` | 警告メッセージのHTML構造とプラグインリスト表示を確認 |

**主要処理フロー**:
- **行3-6**: jenkins-alert-dangerスタイルとCorrectボタンのフォーム
- **行7-18**: 直接依存エラーを持つプラグインの表示
- **行19-32**: 間接依存エラーを持つプラグインの表示（条件付き）

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

```
Jenkins起動時
    │
    └─ PluginWrapper.resolvePluginDependencies()
           │
           ├─ 依存関係エラー検出
           │      └─ dependencyErrors.put(message, isFromFailedPlugin)
           │
           └─ NOTICE.addPlugin(this)

Jenkins管理画面（/manage）
    │
    ├─ AdministrativeMonitor.all()
    │      └─ PluginWrapperAdministrativeMonitor.isActivated()
    │             └─ !plugins.isEmpty()
    │
    └─ message.jelly（表示時）
           ├─ getPlugins()
           ├─ hasOriginalDependencyErrors()
           ├─ getOriginalDependencyErrors()
           ├─ hasDerivedDependencyErrors()
           └─ getDerivedDependencyErrors()
```

### データフロー図

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

プラグインManifest ───▶ resolvePluginDependencies() ───▶ dependencyErrors
                                    │
                            依存関係検証
                                    │
                            NOTICE.addPlugin()
                                    │
管理画面アクセス ───▶ isActivated()判定 ───▶ 警告表示/非表示
                                    │
                            plugins.isEmpty()

Correctボタン ───▶ doAct() ───▶ プラグインマネージャーへリダイレクト
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| PluginWrapper.java | `core/src/main/java/hudson/` | ソース | モニター定義（内部クラス）、依存関係管理 |
| PluginManager.java | `core/src/main/java/hudson/` | ソース | プラグインロード処理 |
| message.jelly | `core/src/main/resources/hudson/PluginWrapper/PluginWrapperAdministrativeMonitor/` | テンプレート | 警告表示UI |
| description.jelly | `core/src/main/resources/hudson/PluginWrapper/PluginWrapperAdministrativeMonitor/` | テンプレート | モニター説明 |
| Messages.properties | `core/src/main/resources/hudson/` | 設定 | 国際化メッセージ |
