# 通知設計書 2-ルートURL未設定警告（RootUrlNotSetMonitor）

## 概要

本ドキュメントは、JenkinsのルートURLが設定されていない、または無効な場合に管理者へ警告を表示するRootUrlNotSetMonitor（ルートURL未設定警告）の通知設計について記述する。

### 本通知の処理概要

RootUrlNotSetMonitorは、JenkinsのルートURL（Jenkins URL）が適切に設定されていない状態を検出し、管理者に対して設定を促す警告メッセージを表示する通知機能である。

**業務上の目的・背景**：JenkinsのルートURLは、ビルド通知メール内のリンク、Webhook URL、外部サービス連携など多くの機能で使用される重要な設定である。URLが未設定または無効な場合、これらの機能が正しく動作しない。通常、SetupWizard（初期設定ウィザード）で設定されるが、開発環境でウィザードを無効化した場合や、管理者が設定を空にした場合に問題が発生する。本通知は、この状態を検出し適切な設定を促すことを目的とする。

**通知の送信タイミング**：Jenkins管理画面（/manage）にアクセスした際に、`isActivated()`メソッドが呼び出され、JenkinsLocationConfigurationからURLを取得して検証する。URLがnullまたは無効な形式の場合に通知が有効化される。

**通知の受信者**：Jenkins.SYSTEM_READ権限を持つユーザーが対象となる。`getRequiredPermission()`でSYSTEM_READを返すため、管理者以外でもシステム読み取り権限があれば警告を確認できる。

**通知内容の概要**：URLがnullの場合と無効な形式の場合で異なるメッセージを表示する。「urlIsNull」または「urlIsInvalid」のメッセージと、設定画面へのリンクが表示される。管理者のみ「Dismiss」ボタンで警告を非表示にできる。

**期待されるアクション**：管理者は設定画面（/configure）に遷移し、有効なJenkins URLを設定することが期待される。URLはUrlHelper.isValidRootUrl()で検証される形式である必要がある。

## 通知種別

アプリ内通知（管理画面バナー表示）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（画面レンダリング時） |
| 優先度 | 中 |
| リトライ | 無（画面表示のため不要） |

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

Jenkins.SYSTEM_READ権限を持つユーザーに対して表示される。管理者権限（ADMINISTER）がなくても、システム読み取り権限があれば警告を確認可能。

## 通知テンプレート

### アプリ内通知の場合

| 項目 | 内容 |
|-----|------|
| 表示位置 | 管理画面上部 |
| アラートタイプ | jenkins-alert-warning（警告） |
| 形式 | HTML |

### 本文テンプレート

```html
<div class="jenkins-alert jenkins-alert-warning">
  <!-- 管理者のみDismissボタン表示 -->
  <l:isAdmin>
    <form method="post" action="${rootURL}/${it.url}/disable">
      <f:submit value="Dismiss"/>
    </form>
  </l:isAdmin>

  <!-- URLがnullの場合 -->
  <j:when test="${it.isUrlNull()}">
    ${%urlIsNull}
  </j:when>
  <!-- URLが無効な場合 -->
  <j:otherwise>
    ${%urlIsInvalid}
  </j:otherwise>

  <!-- 管理者のみアクションリンク表示 -->
  <l:isAdmin>
    <a href="${rootURL}/configure">${%actionUrlContent}</a>
  </l:isAdmin>
</div>
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| rootURL | JenkinsのルートURL | Jenkins.get().getRootUrl() | Yes |
| it.url | モニターのURL | AdministrativeMonitor.getUrl() | Yes |
| it.isUrlNull() | URLがnullかどうか | JenkinsLocationConfiguration.getUrl() == null | Yes |
| urlIsNull | URL未設定時のメッセージ | Messages.properties | Yes |
| urlIsInvalid | URL無効時のメッセージ | Messages.properties | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| 画面操作 | 管理画面（/manage）へのアクセス | JenkinsLocationConfiguration.getUrl() == null または !UrlHelper.isValidRootUrl() | URLが未設定または無効な場合に表示 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| disable()が呼び出された場合 | 管理者が「Dismiss」をクリックした場合、以降表示されない |
| isEnabled() == false | Jenkins設定でこのモニターが無効化されている場合 |
| 有効なURLが設定されている場合 | 正しいURL設定により自動的に非表示 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[管理画面へアクセス] --> B{isEnabled?}
    B -->|No| C[表示しない]
    B -->|Yes| D{isActivated?}
    D -->|No| C
    D -->|Yes| E{URLはnull?}
    E -->|Yes| F[urlIsNullメッセージ表示]
    E -->|No| G[urlIsInvalidメッセージ表示]
    F --> H{ユーザーアクション}
    G --> H
    H -->|設定画面へ| I[/configure へ遷移]
    H -->|Dismiss| J[disable で無効化]
    I --> K[URL設定]
    K --> L[終了]
    J --> L
    C --> L
```

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

### 参照テーブル一覧

該当なし（ファイルベースの設定を参照）

### 参照ファイル

| ファイル | 用途 | 備考 |
|---------|------|------|
| $JENKINS_HOME/jenkins.model.JenkinsLocationConfiguration.xml | JenkinsのURL設定 | JenkinsLocationConfigurationの永続化ファイル |

### 更新ファイル

| ファイル | 操作 | 概要 |
|---------|------|------|
| $JENKINS_HOME/config.xml | UPDATE | disable()呼び出し時にdisabledAdministrativeMonitorsを更新 |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 設定取得失敗 | JenkinsLocationConfiguration取得時の例外 | デフォルト動作（警告表示）にフォールバック |

### リトライ仕様

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

## 配信設定

### レート制限

該当なし（画面表示のため）

### 配信時間帯

制限なし（常時有効）

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

- `@Restricted(NoExternalUse.class)`でクラスは外部使用制限
- getRequiredPermission()でJenkins.SYSTEM_READを返し、読み取り専用アクセスを許可
- Dismissボタンは`<l:isAdmin>`タグで管理者のみに表示
- 設定変更アクションも管理者のみ可能

## 備考

- Symbol: `rootUrlNotSet`
- パッケージ: jenkins.diagnostics
- 導入バージョン: Jenkins 2.119以降（@since 2.119）
- メッセージリソース: jenkins/diagnostics/Messages.properties

---

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

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

### 推奨読解順序

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

JenkinsLocationConfigurationとUrlHelperの関係を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | AdministrativeMonitor.java | `core/src/main/java/hudson/model/AdministrativeMonitor.java` | 基底クラスの仕組み |
| 1-2 | JenkinsLocationConfiguration.java | `core/src/main/java/jenkins/model/JenkinsLocationConfiguration.java` | URL設定の取得方法 |

**読解のコツ**: JenkinsLocationConfiguration.get()でシングルトンインスタンスを取得する点に注目。

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

RootUrlNotSetMonitorクラスがエントリーポイント。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | RootUrlNotSetMonitor.java | `core/src/main/java/jenkins/diagnostics/RootUrlNotSetMonitor.java` | isActivated()でURL検証、isUrlNull()で状態判定 |

**主要処理フロー**:
1. **56-59行目**: `isActivated()` - URLがnullまたは無効かチェック
2. **62-66行目**: `isUrlNull()` - URLがnullかどうかを判定（Jellyで使用）
3. **68-71行目**: `getRequiredPermission()` - SYSTEM_READ権限を返す

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

Jellyテンプレートで警告UIを構成。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | message.jelly | `core/src/main/resources/jenkins/diagnostics/RootUrlNotSetMonitor/message.jelly` | 条件分岐による異なるメッセージ表示 |

**主要処理フロー**:
- **27-31行目**: 管理者のみDismissフォーム表示
- **37-43行目**: isUrlNull()で条件分岐、異なるメッセージ表示
- **45-47行目**: 管理者のみ設定画面へのリンク表示

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

```
Jenkins.getAdministrativeMonitors()
    │
    ├─ RootUrlNotSetMonitor.isEnabled()
    │
    ├─ RootUrlNotSetMonitor.isActivated()
    │      ├─ JenkinsLocationConfiguration.get()
    │      │      └─ getUrl()
    │      └─ UrlHelper.isValidRootUrl()
    │
    └─ RootUrlNotSetMonitor.isUrlNull()
           └─ JenkinsLocationConfiguration.get().getUrl() == null
```

### データフロー図

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

管理画面アクセス ───▶ isActivated()チェック ───▶ 警告バナー表示
                         │
                         ├─ JenkinsLocationConfiguration.getUrl()
                         │          │
                         │          ▼
                         │   jenkins.model.JenkinsLocationConfiguration.xml
                         │
                         └─ UrlHelper.isValidRootUrl()
                                    │
                                    ▼
                            URL形式検証
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| RootUrlNotSetMonitor.java | `core/src/main/java/jenkins/diagnostics/RootUrlNotSetMonitor.java` | ソース | メインクラス |
| AdministrativeMonitor.java | `core/src/main/java/hudson/model/AdministrativeMonitor.java` | ソース | 基底クラス |
| JenkinsLocationConfiguration.java | `core/src/main/java/jenkins/model/JenkinsLocationConfiguration.java` | ソース | URL設定管理 |
| UrlHelper.java | `core/src/main/java/jenkins/util/UrlHelper.java` | ソース | URL検証ユーティリティ |
| message.jelly | `core/src/main/resources/jenkins/diagnostics/RootUrlNotSetMonitor/message.jelly` | テンプレート | 警告UI |
| description.jelly | `core/src/main/resources/jenkins/diagnostics/RootUrlNotSetMonitor/description.jelly` | テンプレート | 説明文 |
| Messages.properties | `core/src/main/resources/jenkins/diagnostics/Messages.properties` | リソース | メッセージ定義 |
| RootUrlNotSetMonitorTest.java | `test/src/test/java/jenkins/diagnostics/RootUrlNotSetMonitorTest.java` | テスト | 単体テスト |
