# 機能設計書 4-ジョブ（Job）

## 概要

本ドキュメントは、Jenkinsの基本的なビルド単位であるジョブ（hudson.model.Job）の機能設計を記述する。ジョブはビルドやタスクの設定・実行を管理する基本単位であり、Jenkinsの中核を担う概念である。

### 本機能の処理概要

Jobクラスは、Jenkinsにおいて監視対象となる実行可能なエンティティを表現する抽象クラスである。実行されるたびにRunオブジェクトとして記録される。

**業務上の目的・背景**：ソフトウェア開発において、ビルド、テスト、デプロイなどの自動化タスクを定義・管理するための基盤が必要である。ジョブはこれらのタスクを設定可能な単位として抽象化し、再利用性と管理性を提供する。

**機能の利用シーン**：新規ビルドジョブの作成、既存ジョブの設定変更、ビルド履歴の参照、ジョブの削除・コピー、ビルドトリガーの設定など、CI/CDパイプラインの構築・運用全般。

**主要な処理内容**：
1. ジョブの作成・設定・保存（config.xml）
2. ビルド番号の管理（nextBuildNumber）
3. ビルド履歴の管理とログローテーション
4. ジョブプロパティの管理（JobProperty）
5. ヘルスレポートの計算と表示
6. ビルドのキュー投入制御
7. パーマリンク（lastBuild, lastSuccessfulBuild等）の管理

**関連システム・外部連携**：SCM（ソースコード管理）、ビルドツール、通知システム、成果物リポジトリ。

**権限による制御**：Item.CREATE（作成）、Item.CONFIGURE（設定変更）、Item.DELETE（削除）、Item.BUILD（ビルド実行）など、操作ごとに権限が定義されている。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | ダッシュボード（View一覧） | 参照画面 | ジョブ一覧の表示 |
| 2 | 新規ジョブ作成 | 主画面 | 新規ジョブの作成処理 |
| 11 | ジョブ詳細 | 主画面 | ジョブの詳細情報表示 |
| 12 | ジョブ設定 | 主画面 | ジョブ設定の表示・編集 |
| 13 | ビルド時間傾向 | 参照画面 | ジョブのビルド時間統計表示 |
| 22 | ノード詳細 | 参照画面 | 関連ジョブの表示 |
| 58 | ラベル詳細 | 参照画面 | ラベルに関連するジョブの表示 |
| 68 | プロジェクト関係図 | 参照画面 | ジョブ間の依存関係図表示 |
| 76 | View設定 | 参照画面 | 表示ジョブのフィルター設定 |

## 機能種別

エンティティ管理 / ビルド単位管理 / 設定管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| name | String | Yes | ジョブ名 | 空白・特殊文字制限 |
| description | String | No | ジョブの説明 | なし |
| keepDependencies | boolean | No | 依存関係の保持 | true/false |
| properties | List<JobProperty> | No | ジョブプロパティ一覧 | なし |
| buildDiscarder | BuildDiscarder | No | ビルド破棄ポリシー | なし |

### 入力データソース

- config.xml: ジョブの設定ファイル（$JENKINS_HOME/jobs/{jobname}/config.xml）
- Web画面: ジョブ設定画面からのフォーム入力
- REST API: /job/{name}/config.xml 経由のXML
- CLI: create-job コマンド

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| nextBuildNumber | int | 次のビルド番号 |
| builds | RunList | ビルド履歴一覧 |
| lastBuild | Run | 最新ビルド |
| lastSuccessfulBuild | Run | 最新成功ビルド |
| lastStableBuild | Run | 最新安定ビルド |
| healthReport | List<HealthReport> | 健全性レポート |

### 出力先

- config.xml: ジョブ設定の永続化
- nextBuildNumber ファイル: ビルド番号の永続化
- builds ディレクトリ: ビルド履歴
- Webインターフェース: ジョブ詳細画面
- REST API: /job/{name}/api/json

## 処理フロー

### 処理シーケンス

```
1. ジョブ作成
   ├─ 名前の検証（ProjectNamingStrategy）
   ├─ ディレクトリ作成（$JENKINS_HOME/jobs/{name}）
   ├─ config.xml 保存
   └─ ItemListener.onCreated() 通知
2. ジョブロード（起動時）
   ├─ config.xml 読み込み
   ├─ nextBuildNumber 読み込み
   ├─ ビルド履歴のインデックス構築
   └─ onLoad() コールバック
3. ビルド実行
   ├─ scheduleBuild() でキューに追加
   ├─ nextBuildNumber インクリメント
   ├─ Run オブジェクト生成
   └─ ビルド完了後に履歴追加
4. ジョブ削除
   ├─ ItemListener.onDeleting() 通知
   ├─ ディレクトリ削除
   └─ ItemListener.onDeleted() 通知
```

### フローチャート

```mermaid
flowchart TD
    A[ジョブ作成要求] --> B{名前検証}
    B -->|OK| C[ディレクトリ作成]
    B -->|NG| D[エラー返却]
    C --> E[config.xml保存]
    E --> F[nextBuildNumber初期化]
    F --> G[ItemListener通知]
    G --> H[完了]

    I[ビルド要求] --> J{holdOffBuildUntilSave?}
    J -->|Yes| K[ビルド保留]
    J -->|No| L[キュー投入]
    L --> M[Executorで実行]
    M --> N[Run生成]
    N --> O[ビルド履歴追加]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | ビルド番号連番 | ビルド番号は1から始まり単調増加 | ビルド実行時 |
| BR-002 | コピー時リセット | コピー作成時はビルド番号を1にリセット | ジョブコピー時 |
| BR-003 | 保存後ビルド許可 | コピー後は設定保存までビルド不可 | ジョブコピー後 |
| BR-004 | ログローテーション | BuildDiscarderに従い古いビルドを削除 | ビルド完了後 |
| BR-005 | 名前変更不可 | ジョブ名は作成後変更不可（リネーム以外） | 常時 |

### 計算ロジック

- ヘルスレポート: HealthReportingActionからの情報を集約してスコア計算
- ビルド時間傾向: 過去のビルド時間からチャートデータを生成

## データベース操作仕様

ファイルベースの永続化を使用。

### ファイル操作一覧

| 操作 | 対象ファイル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 設定保存 | jobs/{name}/config.xml | 書き込み | ジョブ設定の保存 |
| 設定読込 | jobs/{name}/config.xml | 読み取り | ジョブ設定の読み込み |
| ビルド番号 | jobs/{name}/nextBuildNumber | 読み書き | 次ビルド番号管理 |
| ビルド履歴 | jobs/{name}/builds/ | ディレクトリ | ビルド結果格納 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | FormException | 無効なジョブ名 | 有効な名前を指定 |
| - | IOException | config.xml読み書き失敗 | ファイルシステム確認 |
| - | AccessDeniedException | 権限不足 | 適切な権限を付与 |
| - | IllegalStateException | 重複するジョブ名 | 別名を使用 |

### リトライ仕様

設定保存失敗時は即時エラー。自動リトライなし。

## トランザクション仕様

BulkChangeを使用して複数の設定変更をバッチ処理し、最後に一括保存することで整合性を確保。

## パフォーマンス要件

- ジョブロード: ジョブ数に比例（数千ジョブで数十秒）
- ヘルスレポート計算: キャッシュを使用して高速化
- ビルド履歴: LazyBuildMixInで遅延ロード

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

- 権限チェック: Item.CREATE、Item.CONFIGURE、Item.DELETE等
- 設定アクセス制御: config.xmlへのアクセスは権限に依存
- スクリプト実行: ビルドステップでの任意コード実行に注意

## 備考

- Jobは抽象クラス。具体的な実装はFreeStyleProject、WorkflowJob等
- パーマリンク（lastBuild等）はPeepholePermalinkで効率的に管理
- 大量のジョブにはフォルダ（CloudBees Folders Plugin）の使用を推奨

---

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

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

### 推奨読解順序

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

Jobクラスの型パラメータとフィールドを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Job.java | `core/src/main/java/hudson/model/Job.java` | ジェネリクス定義（154行目）、nextBuildNumber（167行目）、properties（200行目）を確認 |
| 1-2 | AbstractItem.java | `core/src/main/java/hudson/model/AbstractItem.java` | 親クラスの基本機能 |

**読解のコツ**: `Job<JobT extends Job<JobT, RunT>, RunT extends Run<JobT, RunT>>` という再帰的なジェネリクス定義は、自己参照型パターン。JobTは具体的なJobサブクラス、RunTは対応するRunサブクラスを指す。

#### Step 2: ビルド番号管理を理解する

ビルド番号の永続化と管理方法を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Job.java | `core/src/main/java/hudson/model/Job.java` | getNextBuildNumberFile()（279-281行目）、saveNextBuildNumber()（287-292行目）を確認 |

**主要処理フロー**:
1. **167行目**: nextBuildNumberフィールドの定義（transient volatile）
2. **228-244行目**: onLoad()でnextBuildNumberファイルから読み込み
3. **254-261行目**: onCopiedFrom()でビルド番号をリセット

#### Step 3: ビルド保留ロジックを理解する

コピー後のビルド保留メカニズムを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Job.java | `core/src/main/java/hudson/model/Job.java` | holdOffBuildUntilSave（173行目）、holdOffBuildUntilUserSave（180行目）の違い |
| 3-2 | Job.java | `core/src/main/java/hudson/model/Job.java` | LastItemListener（263-277行目）の役割 |

#### Step 4: ジョブプロパティを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | JobProperty.java | `core/src/main/java/hudson/model/JobProperty.java` | ジョブプロパティの基底クラス |

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

```
Job<JobT, RunT>
    │
    ├─ nextBuildNumber管理
    │      ├─ getNextBuildNumberFile()
    │      └─ saveNextBuildNumber()
    │
    ├─ ビルド履歴管理
    │      ├─ getBuilds() -> RunList<RunT>
    │      ├─ getLastBuild()
    │      └─ getBuildByNumber(int)
    │
    ├─ プロパティ管理
    │      └─ properties (CopyOnWriteList<JobProperty>)
    │
    └─ ヘルスレポート
           └─ getBuildHealth() -> HealthReport
```

### データフロー図

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

config.xml ─────────────▶ XStream2デシリアライズ ────▶ Jobオブジェクト
                                │
                                ▼
nextBuildNumber ────────▶ ビルド番号読み込み ─────────▶ int値
                                │
                                ▼
ビルド要求 ─────────────▶ scheduleBuild() ───────────▶ Queue.Item
                                │
                                ▼
ビルド完了 ─────────────▶ Run永続化 ─────────────────▶ builds/{number}/
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Job.java | `core/src/main/java/hudson/model/Job.java` | ソース | ジョブ抽象基底クラス |
| AbstractItem.java | `core/src/main/java/hudson/model/AbstractItem.java` | ソース | アイテム基底クラス |
| TopLevelItem.java | `core/src/main/java/hudson/model/TopLevelItem.java` | ソース | トップレベルアイテムインターフェース |
| JobProperty.java | `core/src/main/java/hudson/model/JobProperty.java` | ソース | ジョブプロパティ基底クラス |
| BuildDiscarder.java | `core/src/main/java/jenkins/model/BuildDiscarder.java` | ソース | ビルド破棄ポリシー |
| index.jelly | `core/src/main/resources/hudson/model/Job/index.jelly` | テンプレート | ジョブ詳細画面 |
| configure.jelly | `core/src/main/resources/hudson/model/Job/configure.jelly` | テンプレート | ジョブ設定画面 |
