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

## はじめに

このガイドラインは、Jenkinsのコードベースを効率的に理解するための手引きです。
Javaに精通していないエンジニアでも、段階的に学習できるよう構成されています。

**対象読者:**
- プロジェクトに新規参画するエンジニア
- 他言語からの経験者
- コードレビューを行う担当者

---

## 1. 言語基礎

> このセクションでは、Javaの基本構文と概念を解説します。

### 1.1 プログラム構造

Jenkinsは主にJavaで実装されています。Javaプログラムの基本構造は以下の通りです。

**パッケージ宣言とインポート**

```java
// ファイル: core/src/main/java/jenkins/model/Jenkins.java:28
package jenkins.model;

import static hudson.Util.fixEmpty;
import static hudson.Util.fixNull;
import static hudson.init.InitMilestone.COMPLETED;
// ... 静的インポートと通常のインポート
import hudson.Extension;
import hudson.ExtensionList;
import jenkins.model.Jenkins;
```

**解説:**
- `package`: クラスが属するパッケージ（名前空間）を宣言
- `import`: 他のパッケージのクラスを使用可能にする
- `import static`: 静的メソッドやフィールドを直接参照可能にする

### 1.2 データ型と変数

Javaは静的型付け言語です。変数は宣言時に型を指定します。

**プリミティブ型とクラス型**

```java
// ファイル: core/src/main/java/hudson/Extension.java:85
double ordinal() default 0;

// ファイル: core/src/main/java/hudson/Extension.java:94
boolean optional() default false;
```

**アノテーション付きフィールド宣言**

```java
// ファイル: core/src/main/java/hudson/ExtensionList.java:77-78
@CopyOnWrite
private volatile List<ExtensionComponent<T>> extensions;
```

**解説:**
- `@CopyOnWrite`: Jenkinsカスタムアノテーション（スレッドセーフな更新パターン）
- `volatile`: スレッド間での可視性を保証
- `List<ExtensionComponent<T>>`: ジェネリクスを使用した型パラメータ

### 1.3 制御構造

Javaの制御構造は標準的なif/else、for、whileを使用します。

**条件分岐の例**

```java
// ファイル: core/src/main/java/hudson/Plugin.java:320-321
if (xml.exists())
    xml.unmarshal(this);
```

**ガード節パターン**

```java
// ファイル: core/src/main/java/hudson/Plugin.java:331
if (BulkChange.contains(this))   return;
```

### 1.4 関数/メソッド定義

Jenkinsではメソッドにアノテーションを付与してメタデータを提供することが多いです。

**基本的なメソッド定義**

```java
// ファイル: core/src/main/java/hudson/Plugin.java:165-166
public void start() throws Exception {
}
```

**アノテーション付きメソッド**

```java
// ファイル: core/src/main/java/hudson/Plugin.java:317-322
@Override
public synchronized void load() throws IOException {
    XmlFile xml = getConfigXml();
    if (xml.exists())
        xml.unmarshal(this);
}
```

**解説:**
- `@Override`: 親クラスやインターフェースのメソッドをオーバーライドしていることを明示
- `synchronized`: スレッドセーフを保証
- `throws IOException`: チェック例外を呼び出し元に伝播

### 1.5 モジュール/インポート

JenkinsはMavenマルチモジュール構成を採用しています。

**モジュール構成（pom.xml:52-61）:**

```xml
<modules>
    <module>bom</module>
    <module>websocket/spi</module>
    <module>websocket/jetty12-ee9</module>
    <module>core</module>
    <module>war</module>
    <module>test</module>
    <module>cli</module>
    <module>coverage</module>
</modules>
```

---

## 2. プロジェクト固有の概念

> このセクションでは、Jenkins特有の概念を解説します。

### 2.1 フレームワーク固有の概念

#### Extension Point システム

JenkinsはExtension Pointパターンを採用しており、プラグインが機能を拡張できます。

**ExtensionPointインターフェース**

```java
// ファイル: core/src/main/java/hudson/ExtensionPoint.java:47-55
/**
 * Marker interface that designates extensible components
 * in Jenkins that can be implemented by plugins.
 */
public interface ExtensionPoint {
    // マーカーインターフェース
}
```

**@Extensionアノテーション**

```java
// ファイル: core/src/main/java/hudson/Extension.java:71-117
@Indexable
@Retention(RUNTIME)
@Target({TYPE, FIELD, METHOD})
@Documented
public @interface Extension {
    double ordinal() default 0;      // ソート順
    boolean optional() default false; // オプショナル指定
    YesNoMaybe dynamicLoadable() default MAYBE; // 動的ロード可否
}
```

**使用例:**
- クラスに`@Extension`を付与すると、Jenkinsが自動的にそのインスタンスを作成し、`ExtensionList`に登録
- `ordinal`が高いほど優先度が高い

#### Describable/Descriptorパターン

設定可能なコンポーネントのための双方向パターンです。

**Describableインターフェース**

```java
// ファイル: core/src/main/java/hudson/model/Describable.java:35-50
public interface Describable<T extends Describable<T>> {
    default Descriptor<T> getDescriptor() {
        return Jenkins.get().getDescriptorOrDie(getClass());
    }
}
```

**解説:**
- `Describable`: 設定可能なインスタンス（例: ビルドステップ、トリガー）
- `Descriptor`: メタデータとUI生成を担当するシングルトン
- 慣例的に、`Describable`実装クラスの内部に`DescriptorImpl`というネストクラスを作成

### 2.2 プロジェクト独自のパターン

#### Stapler Webフレームワーク

JenkinsはStaplerを使用してURLをJavaオブジェクトにマッピングします。

**URLマッピングの例:**
- `/job/myproject/` → `Job`オブジェクト
- `/job/myproject/1/` → `Run`オブジェクト（ビルド#1）

#### XStream永続化

Jenkinsは設定をXMLファイルとして永続化します。

```java
// ファイル: core/src/main/java/hudson/Plugin.java:346-349
protected XmlFile getConfigXml() {
    return new XmlFile(Jenkins.XSTREAM,
            new File(Jenkins.get().getRootDir(), wrapper.getShortName() + ".xml"));
}
```

---

## 3. 命名規則

> このセクションでは、プロジェクト全体で使用される命名規則を解説します。

### 3.1 ファイル・ディレクトリ命名

| パターン | 意味 | 例 |
|---------|------|-----|
| `*Test.java` | JUnitテストクラス | `PluginWrapperTest.java` |
| `*Impl.java` | インターフェースの実装 | `DummyImpl` (Plugin内) |
| `*Descriptor.java` | Describableのメタデータ | `TopLevelItemDescriptor.java` |
| `*Action.java` | UIアクション | `RootAction.java`, `CauseAction.java` |
| `*Listener.java` | イベントリスナー | `ItemListener.java`, `RunListener.java` |
| `*Property.java` | 設定プロパティ | `JobProperty.java`, `UserProperty.java` |

### 3.2 クラス・関数・変数命名

| プレフィックス/サフィックス | 意味 | 例 |
|---------------------------|------|-----|
| `Abstract*` | 抽象基底クラス | `AbstractBuild`, `AbstractProject`, `AbstractItem` |
| `*Builder` | ビルドステップ | `Builder`, `Maven` |
| `*Publisher` | ビルド後処理 | `Publisher`, `ArtifactArchiver` |
| `*Wrapper` | ビルドラッパー | `BuildWrapper`, `PluginWrapper` |
| `*Thread` | バックグラウンド処理 | `FingerprintCleanupThread`, `WorkspaceCleanupThread` |
| `*Monitor` | 監視機能 | `AdministrativeMonitor` |
| `do*` | Staplerアクションメソッド | `doDynamic`, `doSubmit` |
| `get*` | ゲッターメソッド | `getDescriptor`, `getWrapper` |
| `is*` | 真偽値ゲッター | `isEnabled`, `isEmpty` |

### 3.3 パッケージ分類一覧

| パッケージ | 役割 |
|-----------|------|
| `hudson` | レガシーコアパッケージ（後方互換性維持） |
| `hudson.model` | コアドメインモデル |
| `hudson.tasks` | ビルドステップ関連 |
| `hudson.security` | セキュリティ・認証 |
| `hudson.slaves` | エージェント管理 |
| `hudson.util` | ユーティリティクラス |
| `jenkins.model` | 新規コアモデル |
| `jenkins.security` | 新規セキュリティ機能 |

---

## 4. ディレクトリ構造

> このセクションでは、プロジェクトのディレクトリ構造を解説します。

```
jenkins-master/
├── bom/                    # Bill of Materials (依存関係管理)
├── cli/                    # CLIモジュール
├── core/                   # コアモジュール（主要なJavaコード）
│   └── src/
│       ├── main/
│       │   └── java/
│       │       ├── hudson/        # レガシーパッケージ
│       │       │   ├── cli/       # CLIコマンド
│       │       │   ├── console/   # コンソール出力
│       │       │   ├── model/     # ドメインモデル
│       │       │   ├── security/  # セキュリティ
│       │       │   ├── slaves/    # エージェント
│       │       │   ├── tasks/     # ビルドステップ
│       │       │   └── util/      # ユーティリティ
│       │       ├── jenkins/       # 新規パッケージ
│       │       │   ├── model/     # 新規モデル
│       │       │   └── security/  # 新規セキュリティ
│       │       └── org/           # 外部互換用
│       └── test/
│           └── java/              # ユニットテスト
├── coverage/               # コードカバレッジ
├── docs/                   # ドキュメント
├── src/                    # フロントエンド資産
│   └── main/
│       ├── js/            # JavaScript
│       └── scss/          # SCSS スタイル
├── test/                   # 統合テスト
├── war/                    # WARパッケージング
│   └── src/main/
│       ├── java/          # WAR固有Java
│       ├── resources/     # リソース
│       └── webapp/        # Webアプリケーション
│           ├── css/       # スタイルシート
│           ├── help/      # ヘルプファイル
│           ├── images/    # 画像
│           ├── scripts/   # JavaScript
│           └── WEB-INF/   # Web設定
└── websocket/              # WebSocketサポート
    ├── spi/               # SPI定義
    └── jetty12-ee9/       # Jetty実装
```

### 各ディレクトリの役割

| ディレクトリ | 役割 | 主要ファイル |
|-------------|------|-------------|
| `core/` | Jenkins本体のコアロジック | `Jenkins.java`, `Job.java`, `Run.java` |
| `war/` | WARファイル生成、Web UI | `web.xml`, `webapp/` |
| `cli/` | コマンドラインインターフェース | CLIコマンド実装 |
| `test/` | 統合テスト | テストヘルパー |
| `bom/` | 依存関係バージョン管理 | `pom.xml` |
| `websocket/` | WebSocketプロトコル | エージェント接続 |
| `src/main/js/` | フロントエンドJavaScript | UI components |

---

## 5. アーキテクチャ

> このセクションでは、プロジェクトのアーキテクチャパターンを解説します。

### 5.1 全体アーキテクチャ

Jenkinsは**プラグインベースのモジュラーアーキテクチャ**を採用しています。

```
┌─────────────────────────────────────────────────────────────────┐
│                         Jenkins WAR                              │
│  ┌───────────────────────────────────────────────────────────┐  │
│  │                    Web Layer (Stapler)                    │  │
│  │        URL Routing / Jelly Views / REST API               │  │
│  └───────────────────────────────────────────────────────────┘  │
│  ┌───────────────────────────────────────────────────────────┐  │
│  │                     Core Layer                             │  │
│  │  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐       │  │
│  │  │   Jenkins   │  │    Queue    │  │   Security  │       │  │
│  │  │  (Singleton)│  │  (Scheduler)│  │   (ACL)     │       │  │
│  │  └─────────────┘  └─────────────┘  └─────────────┘       │  │
│  │  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐       │  │
│  │  │    Job      │  │    Run      │  │    Node     │       │  │
│  │  │  (Project)  │  │  (Build)    │  │  (Agent)    │       │  │
│  │  └─────────────┘  └─────────────┘  └─────────────┘       │  │
│  └───────────────────────────────────────────────────────────┘  │
│  ┌───────────────────────────────────────────────────────────┐  │
│  │              Extension Point Layer                        │  │
│  │   Builder | Publisher | Trigger | SCM | SecurityRealm     │  │
│  └───────────────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────────┘
                              ▼
┌─────────────────────────────────────────────────────────────────┐
│                        Plugins (.jpi)                           │
│    Git | Pipeline | Credentials | Matrix Auth | etc.           │
└─────────────────────────────────────────────────────────────────┘
```

### 5.2 レイヤー構成

| レイヤー | 責務 | 代表的なファイル |
|---------|------|-----------------|
| Web層 | HTTPリクエスト処理、UIレンダリング | `WebAppMain.java`, Jellyビュー |
| コア層 | ドメインロジック、状態管理 | `Jenkins.java`, `Job.java`, `Run.java` |
| 拡張層 | プラグインインターフェース | `ExtensionPoint`, `Descriptor` |
| 永続化層 | 設定・データの保存 | `XmlFile.java`, `XStream2` |
| セキュリティ層 | 認証・認可 | `SecurityRealm`, `AuthorizationStrategy` |

### 5.3 データフロー

**ビルド実行の流れ:**

```
1. ユーザー/トリガー → ビルド要求
2. Queue → ビルドをキューイング
3. Executor → ビルド実行
4. BuildStep (Builder/Publisher) → 各ステップ実行
5. Run → 結果保存
6. Listener → 通知
```

---

## 6. 主要コンポーネント

> このセクションでは、主要なコンポーネントとその連携を解説します。

### 6.1 エントリーポイント

**WebAppMain - Webアプリケーションエントリーポイント**

```java
// ファイル: core/src/main/java/hudson/WebAppMain.java:88
public class WebAppMain implements ServletContextListener {
    // サーブレットコンテナからのコールバックを受け取る
}
```

**Jenkins - シングルトンインスタンス**

```java
// ファイル: core/src/main/java/jenkins/model/Jenkins.java
// Jenkins.get() でシングルトンインスタンスを取得
// 全体の設定、ジョブ、ノード、プラグインを管理
```

### 6.2 ビジネスロジック

**Job - ジョブ（プロジェクト）の基底クラス**

```java
// ファイル: core/src/main/java/hudson/model/Job.java
// ビルド可能なアイテムの基底クラス
// 履歴管理、ヘルスレポート、パーマリンク等を提供
```

**Run - ビルド実行の基底クラス**

```java
// ファイル: core/src/main/java/hudson/model/Run.java
// 個々のビルド実行を表現
// ログ、成果物、テスト結果等を管理
```

**Queue - ビルドキュー**

```java
// ファイル: core/src/main/java/hudson/model/Queue.java
// ビルド要求のキューイングとスケジューリング
// Executor への割り当てを管理
```

### 6.3 データアクセス

**XmlFile - XML永続化**

```java
// ファイル: core/src/main/java/hudson/XmlFile.java
// XStream を使用した XML シリアライズ/デシリアライズ
// 設定ファイル（config.xml等）の読み書き
```

**FilePath - リモートファイル操作**

```java
// ファイル: core/src/main/java/hudson/FilePath.java
// エージェント上のファイルシステム操作
// ローカル/リモートの透過的なファイルアクセス
```

### 6.4 ユーティリティ/共通機能

**Util - 汎用ユーティリティ**

```java
// ファイル: core/src/main/java/hudson/Util.java
// 文字列操作、ファイル操作、時間計算等の共通機能
```

**Functions - Jelly用ユーティリティ**

```java
// ファイル: core/src/main/java/hudson/Functions.java
// Jellyビューから呼び出されるユーティリティメソッド
```

---

## 7. よく使われるパターン

> このセクションでは、コード内で頻出するパターンを解説します。

### パターン一覧

| パターン | 説明 | 出現頻度 | 代表的なファイル |
|---------|------|---------|-----------------|
| Extension Point | プラグイン拡張ポイント | 高 | `ExtensionPoint.java`, `Extension.java` |
| Describable/Descriptor | 設定可能コンポーネント | 高 | `Describable.java`, `Descriptor.java` |
| Singleton | 単一インスタンス | 中 | `Jenkins.java` |
| Listener | イベント通知 | 高 | `*Listener.java` |
| Stapler URL Mapping | URL-Objectマッピング | 高 | `do*` メソッド |

### 各パターンの詳細

#### パターン1: Extension Point

**目的:** プラグインによる機能拡張を可能にする

**実装例:**
```java
// ファイル: core/src/main/java/hudson/Extension.java:71-76
@Indexable
@Retention(RUNTIME)
@Target({TYPE, FIELD, METHOD})
@Documented
public @interface Extension {
    double ordinal() default 0;
}
```

**使用例:**
```java
// プラグインで新しい Builder を追加
@Extension
public class MyBuilder extends Builder {
    @Extension
    public static class DescriptorImpl extends BuildStepDescriptor<Builder> {
        // ...
    }
}
```

**解説:** `@Extension`を付与したクラスは、Jenkinsの起動時に自動的に検出・登録されます。

#### パターン2: Describable/Descriptor

**目的:** 設定UIの自動生成とインスタンス管理

**実装例:**
```java
// ファイル: core/src/main/java/hudson/model/Describable.java:35-50
public interface Describable<T extends Describable<T>> {
    default Descriptor<T> getDescriptor() {
        return Jenkins.get().getDescriptorOrDie(getClass());
    }
}
```

**解説:**
- `Describable`: 設定可能なオブジェクト（インスタンスは複数存在可能）
- `Descriptor`: メタデータを提供するシングルトン（クラスごとに1つ）
- Jellyビューと連携してUI自動生成

#### パターン3: Listener パターン

**目的:** 疎結合なイベント通知

**代表的なListenerインターフェース:**
- `ItemListener`: ジョブの作成・削除等
- `RunListener`: ビルドの開始・終了
- `SaveableListener`: 設定の保存
- `ComputerListener`: エージェントの接続・切断

---

## 8. 業務フロー追跡の実践例

> このセクションでは、実際の業務フローをコードで追跡する方法を解説します。

### 8.1 フロー追跡の基本手順

1. エントリーポイントを特定
2. 処理の流れを追跡（呼び出し関係を追う）
3. データの変換を確認
4. 最終的な出力を確認

### 8.2 フロー追跡の実例

#### 例1: ジョブ実行フロー

**概要:** ユーザーがビルドを実行してから結果が保存されるまでの流れ

**処理フロー:**
```
User Request → Queue → Executor → BuildStep → Run → Persistence
```

**詳細な追跡:**

1. **ビルド要求の受付** (`Job.java`)
   - `doBuild()` メソッドがHTTPリクエストを受け取る
   - `Queue.schedule2()` でビルドをキューに追加

2. **キューイング** (`Queue.java`)
   - `ScheduleResult` を返却
   - 適切な Executor が空くまで待機

3. **ビルド実行** (`Executor.java`)
   - キューからタスクを取得
   - `Run` インスタンスを作成
   - `BuildStep` を順次実行

4. **結果保存** (`Run.java`)
   - `save()` でXMLファイルに永続化
   - `RunListener` に通知

### 8.3 フロー追跡チェックリスト

- [ ] エントリーポイントを特定したか
- [ ] 呼び出し関係を把握したか
- [ ] データの変換ポイントを確認したか
- [ ] エラーハンドリングを確認したか
- [ ] 最終的な出力を確認したか

---

## 9. 設計書の参照順序

> このセクションでは、プロジェクト理解のための設計書参照順序を案内します。

### 9.1 目的別ロードマップ

#### 全体像を把握したい場合
1. `README.md` - プロジェクト概要
2. `CONTRIBUTING.md` - 開発環境構築
3. `docs/MAINTAINERS.adoc` - メンテナ向けガイド
4. `pom.xml` - モジュール構成

#### 特定機能を理解したい場合
1. 機能一覧で対象機能を特定
2. 該当する `hudson.model` または `jenkins.model` のクラスを確認
3. 関連する `ExtensionPoint` を確認
4. テストコードで使用例を確認

#### 改修作業を行う場合
1. 対象機能のクラス階層を把握
2. `Descriptor` があれば設定UIの関連を確認
3. `Listener` があればイベント連携を確認
4. 既存テストケースを確認

### 9.2 ドキュメント一覧

| ドキュメント | 概要 | 参照タイミング |
|-------------|------|---------------|
| README.md | プロジェクト概要 | 初回参照 |
| CONTRIBUTING.md | 開発ガイド | 開発開始時 |
| docs/MAINTAINERS.adoc | メンテナガイド | 深い理解が必要時 |
| Jenkins公式ドキュメント | 詳細仕様 | 機能詳細確認時 |

---

## 10. トラブルシューティング

> このセクションでは、コードリーディング時によくある問題と解決法を解説します。

### よくある疑問と回答

#### Q: `hudson` パッケージと `jenkins` パッケージの違いは？
A: `hudson` は旧名称時代からのレガシーパッケージで、後方互換性のために維持されています。`jenkins` は新しい機能を追加する場合に使用されます。両者は共存しており、必要に応じて相互参照しています。

#### Q: `Describable` と `Descriptor` の関係が分かりません
A: `Describable` は設定可能なインスタンス（例: 特定のビルドステップ設定）、`Descriptor` はそのクラスに関するメタデータを持つシングルトンです。UIは `Descriptor` 経由で生成され、実際の設定値は `Describable` インスタンスに保持されます。

#### Q: `@Extension` アノテーションの仕組みは？
A: Java Annotation Processing と SezPoz ライブラリを使用しています。コンパイル時にアノテーション情報がインデックス化され、実行時に `ExtensionFinder` がそれを読み取って `ExtensionList` を構築します。

#### Q: Stapler の URL マッピングルールは？
A: オブジェクトの `get*()` メソッドと `do*()` メソッドがURLパスにマッピングされます。例えば `/job/myproject/` は Jenkins インスタンスの `getJob("myproject")` に対応します。

### デバッグのヒント

1. **ログ出力の確認**: Jenkins は `java.util.logging` を使用。`Manage Jenkins > System Log` で確認可能
2. **Script Console**: Groovy スクリプトで内部状態を確認可能
3. **Remote Debug**: Maven Jetty プラグインでデバッグ実行可能

---

## 付録

### A. 用語集

| 用語 | 説明 |
|-----|------|
| Agent | ビルドを実行するリモートマシン（旧称: Slave） |
| Controller | Jenkins本体が動作するマシン（旧称: Master） |
| Executor | 並列ビルドを実行するスロット |
| Extension Point | プラグインが拡張できるポイント |
| Item | Jenkins管理対象（Job, Folder等） |
| Job | ビルド可能なプロジェクト |
| Node | Controller または Agent |
| Run | 個々のビルド実行 |
| Workspace | ビルド作業ディレクトリ |

### B. ファイル一覧

| ファイル/ディレクトリ | 説明 | 主な内容 |
|---------------------|------|---------|
| `jenkins/model/Jenkins.java` | メインシングルトン | グローバル設定、ジョブ管理 |
| `hudson/model/Job.java` | ジョブ基底クラス | ビルド履歴、設定管理 |
| `hudson/model/Run.java` | ビルド基底クラス | ログ、成果物、結果 |
| `hudson/model/Queue.java` | ビルドキュー | スケジューリング |
| `hudson/Extension.java` | 拡張アノテーション | プラグイン登録 |
| `hudson/Plugin.java` | プラグイン基底 | ライフサイクル管理 |
| `hudson/tasks/Builder.java` | ビルドステップ | ビルド処理実行 |
| `hudson/tasks/Publisher.java` | ポストビルド | 結果処理 |

### C. 参考資料

- [Jenkins 公式ドキュメント](https://www.jenkins.io/doc/)
- [Jenkins 開発者ガイド](https://www.jenkins.io/doc/developer/)
- [Extension Points 一覧](https://www.jenkins.io/redirect/developer/extension-points)
- [Stapler フレームワーク](https://stapler.kohsuke.org/)
- [Java 公式ドキュメント](https://docs.oracle.com/en/java/)
