# 機能設計書 25-SCM連携

## 概要

本ドキュメントは、JenkinsのSCM連携（SCM）機能の設計仕様を定義する。SCMクラスは、ソースコード管理システムとJenkinsを接続するための抽象化レイヤーを提供する拡張ポイントである。

### 本機能の処理概要

SCM（Source Code Management）機能は、Git、Subversion、CVSなど各種ソースコード管理システムとJenkinsを統合するための抽象基底クラスと拡張ポイントを提供する。

**業務上の目的・背景**：継続的インテグレーションの基本要件として、ソースコードリポジトリからコードをチェックアウトし、変更を検知する機能が必要である。SCMクラスは、異なるSCMシステムに対して共通のインターフェースを提供し、プラグインによる拡張を可能にする。

**機能の利用シーン**：
- Gitリポジトリからのソースコード取得
- Subversionリポジトリとの連携
- マルチSCM環境での複数リポジトリからのチェックアウト
- ポーリングによる変更検知
- 変更ログ（ChangeLogSet）の取得

**主要な処理内容**：
1. ワークスペースへのソースコードチェックアウト（checkout）
2. リポジトリの変更検知（poll）
3. 変更ログの生成（calcRevisionsFromBuild）
4. リポジトリブラウザとの連携
5. 環境変数の提供（buildEnvironment）

**関連システム・外部連携**：各種SCMプラグイン（Git Plugin、Subversion Plugin等）、RepositoryBrowser、ChangeLogSet、Trigger機構との連携。

**権限による制御**：SCM設定はジョブの設定権限を持つユーザーが変更可能。SCMへのアクセスには別途認証情報が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 12 | ジョブ設定 | 主画面 | SCM設定の編集 |
| 44 | SCMポーリングログ | 補助画面 | ポーリング結果の確認 |

## 機能種別

拡張ポイント / ソースコード管理

## 入力仕様

### 入力パラメータ（checkoutメソッド）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| build | Run<?,?> | Yes | 実行中のビルド | null不可 |
| launcher | Launcher | Yes | プロセス起動用ランチャー | null不可 |
| workspace | FilePath | Yes | チェックアウト先ディレクトリ | null不可 |
| listener | TaskListener | Yes | ログ出力用リスナー | null不可 |
| changelogFile | File | No | 変更ログ出力先ファイル | nullの場合は変更ログなし |
| baseline | SCMRevisionState | No | 比較対象のリビジョン状態 | nullの場合は初回チェックアウト |

### 入力パラメータ（pollメソッド）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| project | Job<?,?> | Yes | ポーリング対象ジョブ | null不可 |
| launcher | Launcher | Yes | プロセス起動用ランチャー | null不可 |
| workspace | FilePath | No | ワークスペース | nullの場合あり |
| listener | TaskListener | Yes | ログ出力用リスナー | null不可 |
| baseline | SCMRevisionState | Yes | 比較対象のリビジョン状態 | null不可 |

### 入力データソース

ジョブ設定画面からの設定値。リポジトリURL、認証情報、ブランチ指定等はSCM実装固有。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| PollingResult | PollingResult | ポーリング結果（変更有無） |
| SCMRevisionState | SCMRevisionState | チェックアウト時点のリビジョン状態 |
| ChangeLogSet | ChangeLogSet | 変更ログエントリのセット |

### 出力先

- ワークスペースディレクトリへのソースコードチェックアウト
- 変更ログファイル（changelog.xml等）

## 処理フロー

### 処理シーケンス

```
1. ビルド開始時のチェックアウト処理
   └─ SCM.checkout() 呼び出し
   └─ ワークスペースにソースコードを取得
   └─ 変更ログファイルを生成
   └─ SCMRevisionStateを返却
2. ポーリング時の変更検知
   └─ SCM.poll() 呼び出し
   └─ 現在のリポジトリ状態を取得
   └─ baselineと比較
   └─ PollingResultを返却
3. 変更ログ解析
   └─ SCM.createChangeLogParser() で解析器を取得
   └─ 変更ログファイルをパース
   └─ ChangeLogSetを生成
```

### フローチャート

```mermaid
flowchart TD
    A[ビルド開始] --> B[SCM.checkout]
    B --> C{ワークスペース存在?}
    C -->|Yes| D[増分チェックアウト]
    C -->|No| E[フルチェックアウト]
    D --> F[変更ログ生成]
    E --> F
    F --> G[SCMRevisionState返却]
    G --> H[ビルドステップ実行]

    I[ポーリング開始] --> J[SCM.poll]
    J --> K[リポジトリ状態取得]
    K --> L{baseline比較}
    L -->|変更あり| M[BUILD_NOW返却]
    L -->|変更なし| N[NO_CHANGES返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | NullSCM対応 | SCMが設定されていない場合はNullSCMが使用される | SCM未設定時 |
| BR-002 | ワークスペースなしポーリング | requiresWorkspaceForPollingがfalseの場合、ワークスペースなしでポーリング可能 | ポーリング時 |
| BR-003 | 変更ログファイル | changelogFileがnullの場合は変更ログを生成しない | チェックアウト時 |
| BR-004 | マルチSCM | processWorkspaceBeforeDeletionで削除前処理が可能 | ワークスペース削除時 |

### 計算ロジック

特になし（SCM実装依存）。

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 設定保存 | config.xml | INSERT/UPDATE | SCM設定の永続化 |
| 変更ログ保存 | changelog.xml | INSERT | ビルドごとの変更ログ |

### テーブル別操作詳細

#### config.xml（ジョブ設定ファイル）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT/UPDATE | scm | SCM設定（実装依存） | XMLシリアライズ |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | IOException | チェックアウト時のI/Oエラー | ビルド失敗 |
| - | InterruptedException | ユーザーによる中断 | ビルド中止 |
| - | AbortException | SCMエラー（認証失敗等） | ビルド失敗、ログ出力 |

### リトライ仕様

SCMクラス自体にリトライ機能はない。各SCM実装でリトライを実装可能。

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

トランザクション管理はない。チェックアウト処理は外部SCMシステムへの操作であり、ロールバックは不可。

## パフォーマンス要件

- 大規模リポジトリの場合、浅いクローン（shallow clone）の使用を推奨
- ポーリングはSCMサーバーへの負荷を考慮して適切な間隔を設定

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

- SCMアクセス用の認証情報はCredentialsプラグインで安全に管理
- チェックアウト時の認証情報がログに出力されないよう配慮
- buildEnvironmentで環境変数に機密情報を含めない

## 備考

- SCMはDescribableとExtensionPointを実装する抽象クラス
- 具体的な実装はプラグインで提供（Git Plugin、Subversion Plugin等）
- NullSCMはSCM未設定時のデフォルト実装

---

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

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

### 推奨読解順序

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

SCMクラスの基本構造とフィールドを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | SCM.java | `core/src/main/java/hudson/scm/SCM.java` | 抽象クラス定義、フィールド（browser等） |

**読解のコツ**: SCMは抽象クラスであり、checkout()とcalcRevisionsFromBuild()が主要な抽象メソッド。RepositoryBrowserをオプションで保持可能。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | SCM.java | `core/src/main/java/hudson/scm/SCM.java` | checkout()メソッド |

**主要処理フロー**:
- **207-220行目**: checkout() - ワークスペースへのチェックアウト（抽象メソッド）
- **229-241行目**: checkout()の別シグネチャ（旧API互換）
- **312-330行目**: poll() - 変更検知ポーリング

#### Step 3: ポーリング処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | SCM.java | `core/src/main/java/hudson/scm/SCM.java` | poll()、compareRemoteRevisionWith() |

**主要処理フロー**:
- **312-330行目**: poll() - ポーリングのメインメソッド
- **340-360行目**: compareRemoteRevisionWith() - リビジョン比較
- **276-280行目**: requiresWorkspaceForPolling() - ポーリングにワークスペースが必要か

#### Step 4: 補助機能を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | SCM.java | `core/src/main/java/hudson/scm/SCM.java` | buildEnvironment()、getEffectiveBrowser() |

**主要処理フロー**:
- **371-380行目**: buildEnvironment() - 環境変数の追加
- **126-134行目**: getEffectiveBrowser() - リポジトリブラウザの取得
- **382-390行目**: createChangeLogParser() - 変更ログパーサーの取得

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

```
AbstractBuild.run()
    │
    ├─ BuildWrapper.preCheckout()
    │
    ├─ SCM.checkout(build, launcher, workspace, listener, changelogFile, baseline)
    │      │
    │      ├─ [実装依存] リポジトリからチェックアウト
    │      ├─ [実装依存] 変更ログファイル生成
    │      └─ SCMRevisionState返却
    │
    ├─ SCM.createChangeLogParser()
    │      └─ ChangeLogParser取得
    │
    └─ ChangeLogParser.parse()
           └─ ChangeLogSet生成

SCMTrigger.Runner.run()
    │
    └─ SCM.poll(project, launcher, workspace, listener, baseline)
           │
           ├─ compareRemoteRevisionWith()
           │      └─ リモートリビジョン比較
           │
           └─ PollingResult返却
```

### データフロー図

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

リポジトリURL        SCM.checkout()
認証情報         ├─ リポジトリ接続 ───────▶     ワークスペース
ブランチ指定      ├─ ソースコード取得              (ソースコード)
                ├─ 変更ログ生成 ──────────▶     changelog.xml
                └─ リビジョン記録 ─────────▶     SCMRevisionState

SCMRevisionState   SCM.poll()
(baseline)      ├─ リモート状態取得
                ├─ 比較処理 ──────────────▶     PollingResult
                └─ ログ出力 ──────────────▶     polling.log
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| SCM.java | `core/src/main/java/hudson/scm/SCM.java` | ソース | SCM抽象基底クラス |
| NullSCM.java | `core/src/main/java/hudson/scm/NullSCM.java` | ソース | SCM未設定時のデフォルト実装 |
| SCMRevisionState.java | `core/src/main/java/hudson/scm/SCMRevisionState.java` | ソース | リビジョン状態の抽象クラス |
| PollingResult.java | `core/src/main/java/hudson/scm/PollingResult.java` | ソース | ポーリング結果 |
| ChangeLogSet.java | `core/src/main/java/hudson/scm/ChangeLogSet.java` | ソース | 変更ログセット |
| ChangeLogParser.java | `core/src/main/java/hudson/scm/ChangeLogParser.java` | ソース | 変更ログパーサー抽象クラス |
| RepositoryBrowser.java | `core/src/main/java/hudson/scm/RepositoryBrowser.java` | ソース | リポジトリブラウザ抽象クラス |
| SCMDescriptor.java | `core/src/main/java/hudson/scm/SCMDescriptor.java` | ソース | SCM用Descriptor基底クラス |
