# 通知設計書 28-SCMポーリングトリガー

## 概要

本ドキュメントは、定期的にSCM（ソースコード管理システム）をポーリングし、変更を検出した場合にビルドをトリガーする通知機能（SCMTrigger）の設計仕様を定義する。

### 本通知の処理概要

本通知は、cronスケジュールに従って定期的にSCMリポジトリをポーリングし、前回のビルド以降に変更があった場合にビルドを自動的にトリガーする機能である。また、SCMプラグインからのpost-commitフック通知を受け取ってポーリングを開始することも可能である。

**業務上の目的・背景**：継続的インテグレーション（CI）の基本は、ソースコードの変更を検出して自動的にビルドを実行することである。SCMTriggerは、リポジトリへのコミットを監視し、変更があった場合にのみビルドを実行することで、無駄なビルドを削減しつつ、変更に対する素早いフィードバックを提供する。

**通知の送信タイミング**：設定されたcronスケジュールに従って定期的に実行されるか、post-commitフック経由でトリガーされる。変更が検出された場合にビルドがトリガーされる。

**通知の受信者**：プロジェクトのビルドキューに対してトリガーが送信される。ビルドログにはポーリング結果が出力される。

**通知内容の概要**：SCMTriggerCauseを設定し、ポーリングログをビルドに関連付ける。

**期待されるアクション**：プロジェクトのビルドが自動的に開始される。

## 通知種別

ビルドトリガー（定期実行/イベント駆動）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 非同期（SequentialExecutionQueue経由） |
| 優先度 | 中（quietPeriod適用） |
| リトライ | 無し |

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

1. cronスケジュール（scmpoll_spec）に従ってポーリングを実行
2. SCMTriggerItem.poll()でSCMの変更をチェック
3. 変更があった場合にscheduleBuild2()を呼び出し

## 通知テンプレート

### ビルドログ出力

| 項目 | 内容 |
|-----|------|
| ポーリング開始 | Started on {date} |
| ポーリング完了 | Done. Took {duration} |
| 変更あり | Changes found |
| 変更なし | No changes |
| トリガー成功 | SCM changes detected in {project}. Triggering #{buildNumber} |
| 既にキュー内 | SCM changes detected in {project}. Job is already in the queue |

### ビルド原因メッセージ

```
Started by an SCM change
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| scmpoll_spec | cronスケジュール式 | 設定値 | Yes |
| ignorePostCommitHooks | post-commitフックを無視するか | 設定値（デフォルトfalse） | No |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| スケジュール | cronスケジュール実行 | 変更あり | 定期ポーリング |
| post-commit | SCMプラグインからの通知 | 変更あり | フック経由（ignorePostCommitHooks=falseの場合） |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| 変更なし | poll()がNO_CHANGESを返した場合 |
| ignorePostCommitHooks=true | post-commitフック経由の場合のみ抑止 |
| SCMDecisionHandler.veto | ポーリングが拒否された場合 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[cronスケジュール実行] --> B{SCMDecisionHandler.veto?}
    B -->|Yes| C[スキップログ出力]
    B -->|No| D[Runner.runPolling]
    D --> E[SCMTriggerItem.poll]
    E --> F{変更あり?}
    F -->|No| G[No changes ログ]
    F -->|Yes| H[Changes found ログ]
    H --> I[SCMTriggerCause作成]
    I --> J[scheduleBuild2]
    J --> K{成功?}
    K -->|Yes| L[Triggeringログ]
    K -->|No| M[In Queueログ]
```

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

### 参照テーブル一覧

該当なし（ファイルシステム上のポーリングログを使用）

### 参照データ

| データ | 内容 |
|--------|------|
| scm-polling.log | プロジェクトルートのポーリングログファイル |
| polling.log | ビルドルートのポーリングログファイル |

### 更新対象

| 対象 | 操作 | 概要 |
|------|------|------|
| ビルドキュー | INSERT | プロジェクトのビルドを投入 |
| CauseAction | INSERT | SCMTriggerCauseを設定 |
| polling.log | INSERT | ポーリングログをビルドに保存 |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| SCMポーリングエラー | SCM接続失敗等 | エラーログ出力、ビルドはトリガーしない |
| ファイル書き込みエラー | ログファイル書き込み失敗 | IOExceptionログ出力 |
| キュー渋滞 | ポーリングスレッドが枯渇 | AdministrativeMonitor表示 |

### リトライ仕様

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

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| ポーリングスレッド数 | 5-100（デフォルト10） |
| スレッド枯渇閾値 | STARVATION_THRESHOLD（デフォルト1時間） |

### 配信時間帯

cronスケジュールで指定

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

- SCMの認証情報はプロジェクトの設定に従う
- ポーリングログにはSCMの詳細情報が含まれる場合がある
- post-commitフックはSCMプラグインのセキュリティ設定に依存

## 備考

- @Symbolで"pollSCM"として参照可能
- SequentialExecutionQueueで同一プロジェクトの重複ポーリングを防止
- AdministrativeMonitorImpl（No.17）でキュー渋滞を監視
- synchronousPollingオプションでTrigger.Cronと同期実行可能

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | SCMTrigger.java | `core/src/main/java/hudson/triggers/SCMTrigger.java` | フィールド定義（106-108行目） |

**読解のコツ**: scmpoll_specはcron式、ignorePostCommitHooksはboolean。

#### Step 2: トリガー実行を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | SCMTrigger.java | `core/src/main/java/hudson/triggers/SCMTrigger.java` | run()メソッド（160-194行目） |

**主要処理フロー**:
1. **179-191行目**: synchronousPollingの場合は直接実行、そうでなければキューに投入
2. **192行目**: clogCheck()でキュー渋滞をチェック

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | SCMTrigger.java | `core/src/main/java/hudson/triggers/SCMTrigger.java` | Runner内部クラス（555-702行目） |

**主要処理フロー**:
1. **637-658行目**: SCMDecisionHandler.vetoチェック
2. **664行目**: runPolling()でSCMをポーリング
3. **667-681行目**: 変更があった場合にscheduleBuild2呼び出し

#### Step 4: ビルド原因を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | SCMTrigger.java | `core/src/main/java/hudson/triggers/SCMTrigger.java` | SCMTriggerCause内部クラス（708-776行目） |

**主要処理フロー**:
- **742-755行目**: onAddedTo()でpolling.logをビルドに保存
- **758-759行目**: getShortDescription()でメッセージを返す

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

```
cronスケジュール実行
    │
    └─ run()
           │
           ├─ synchronousPolling?
           │      ├─ Yes: Runner.run() 直接実行
           │      └─ No: queue.execute(Runner)
           │
           └─ Runner.run()
                  │
                  ├─ SCMDecisionHandler.firstShouldPollVeto()
                  │
                  ├─ runPolling()
                  │      └─ job().poll(listener)
                  │
                  └─ 変更あり?
                         │
                         └─ scheduleBuild2(SCMTriggerCause)
                                │
                                └─ BuildAction設定
```

### データフロー図

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

scmpoll_spec ────▶ CronTabList.create() ──┐
                                           │
cronスケジュール ───────────────────────────┼─▶ run()
                                           │       │
                                           │       ▼
                                           │  SequentialExecutionQueue
                                           │       │
                                           │       ▼
                                           └─ Runner.run()
                                                   │
                                                   ▼
SCM ─────────────────────────────────▶ poll()
                                           │
                                           ▼
                                   PollingResult
                                           │
                                           ▼
                                   scheduleBuild2()
                                           │
                                           ▼
                               SCMTriggerCause + polling.log
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| SCMTrigger.java | `core/src/main/java/hudson/triggers/SCMTrigger.java` | ソース | メイントリガー実装 |
| SCMTriggerItem.java | `core/src/main/java/jenkins/triggers/SCMTriggerItem.java` | ソース | poll()インターフェース |
| SCMDecisionHandler.java | `core/src/main/java/jenkins/scm/SCMDecisionHandler.java` | ソース | ポーリング拒否ハンドラ |
| SCMTriggerTest.java | `test/src/test/java/hudson/triggers/SCMTriggerTest.java` | テスト | 単体テスト |
