# 機能設計書：47-パイプライン実行

## 1. 機能概要

### 1.1 機能の目的
パイプライン実行機能は、GitLab CI/CDの中核を成す機能であり、`.gitlab-ci.yml`に定義されたCI/CDパイプラインを作成・実行・管理する。プッシュイベント、マージリクエスト、スケジュール、手動実行など様々なトリガーソースに対応し、ジョブの実行、ステータス管理、成果物の管理を行う。

### 1.2 関連画面
| 画面ID | 画面名 | パス |
|--------|--------|------|
| SCR-PIPELINES | パイプライン一覧 | `/:namespace/:project/-/pipelines` |
| SCR-PIPELINE | パイプライン詳細 | `/:namespace/:project/-/pipelines/:id` |
| SCR-PIPELINE-NEW | パイプライン作成 | `/:namespace/:project/-/pipelines/new` |
| SCR-PIPELINE-CHARTS | パイプライン分析 | `/:namespace/:project/-/pipelines/charts` |

### 1.3 関連API
| APIエンドポイント | メソッド | 概要 |
|-------------------|----------|------|
| `/projects/:id/pipelines` | GET | パイプライン一覧取得 |
| `/projects/:id/pipelines` | POST | パイプライン作成 |
| `/projects/:id/pipelines/:pipeline_id` | GET | パイプライン詳細取得 |
| `/projects/:id/pipelines/:pipeline_id` | DELETE | パイプライン削除 |
| `/projects/:id/pipelines/:pipeline_id/retry` | POST | パイプライン再実行 |
| `/projects/:id/pipelines/:pipeline_id/cancel` | POST | パイプラインキャンセル |
| `/projects/:id/pipelines/latest` | GET | 最新パイプライン取得 |

## 2. データモデル

### 2.1 主要エンティティ

#### Ci::Pipeline
```
p_ci_pipelines テーブル（パーティションテーブル）
├── id: bigint (PK)
├── partition_id: integer (PK)
├── project_id: bigint (FK)
├── user_id: bigint (FK)
├── ref: varchar(300)
├── sha: varchar(64)
├── before_sha: varchar(64)
├── source_sha: varchar(64)
├── target_sha: varchar(64)
├── tag: boolean
├── status: varchar
├── source: smallint
├── config_source: smallint
├── failure_reason: smallint
├── locked: smallint
├── iid: integer
├── duration: integer
├── started_at: timestamp
├── finished_at: timestamp
├── created_at: timestamp
├── updated_at: timestamp
├── yaml_errors: text
├── protected: boolean
├── merge_request_id: bigint (FK)
├── external_pull_request_id: bigint (FK)
├── pipeline_schedule_id: bigint (FK)
├── auto_canceled_by_id: bigint (FK)
└── ci_ref_id: bigint (FK)

定数:
- MAX_REF_LENGTH = 300
- MAX_SHA_LENGTH = 64
- YAML_ERRORS_MAX_LENGTH = 100KB
- COUNT_FAILED_JOBS_LIMIT = 101
- INPUTS_LIMIT = 20
- MAX_OPEN_MERGE_REQUESTS_REFS = 4
- DEFAULT_CONFIG_PATH = '.gitlab-ci.yml'
```

#### source enum（パイプラインソース）
```
- push: プッシュイベント
- web: Web UI
- trigger: トリガー
- schedule: スケジュール
- api: API
- external: 外部
- pipeline: 親パイプライン
- chat: ChatOps
- webide: Web IDE
- merge_request_event: マージリクエスト
- external_pull_request_event: 外部プルリクエスト
- parent_pipeline: 親パイプライン（子パイプライン生成時）
- ondemand_dast_scan: オンデマンドDASTスキャン
- ondemand_dast_validation: オンデマンドDAST検証
- security_orchestration_policy: セキュリティポリシー
```

#### status（ステータス状態機械）
```
状態:
- created: 作成済み
- waiting_for_resource: リソース待ち
- preparing: 準備中
- pending: 保留中
- running: 実行中
- success: 成功
- failed: 失敗
- canceled: キャンセル済み
- canceling: キャンセル中
- skipped: スキップ
- manual: 手動
- scheduled: スケジュール済み
- waiting_for_callback: コールバック待ち

遷移イベント:
- enqueue: pending/runningへ遷移
- request_resource: waiting_for_resourceへ遷移
- prepare: preparingへ遷移
- run: runningへ遷移
- skip: skippedへ遷移
- drop: failedへ遷移
- succeed: successへ遷移
- start_cancel: cancelingへ遷移
- cancel: canceledへ遷移
- block: manualへ遷移
- delay: scheduledへ遷移
```

#### failure_reason enum（失敗理由）
```
- unknown_failure: 不明な失敗
- config_error: 設定エラー
- external_validation_failure: 外部検証失敗
- user_not_verified: ユーザー未検証
- activity_limit_exceeded: アクティビティ制限超過
- size_limit_exceeded: サイズ制限超過
- job_activity_limit_exceeded: ジョブアクティビティ制限超過
- deployments_limit_exceeded: デプロイメント制限超過
- project_deleted: プロジェクト削除
- filtered_by_rules: rulesでフィルタ
- filtered_by_workflow_rules: workflowルールでフィルタ
```

### 2.2 ER図
```
┌─────────────────────┐      ┌──────────────────┐
│     Project         │      │      User        │
├─────────────────────┤      ├──────────────────┤
│ id                  │◄─────│ id               │
│ ...                 │      │ ...              │
└─────────────────────┘      └──────────────────┘
         │                            │
         │1                           │1
         ▼ *                          ▼ *
┌─────────────────────────────────────────────────┐
│                  Ci::Pipeline                    │
├─────────────────────────────────────────────────┤
│ id, partition_id                                 │
│ project_id, user_id                             │
│ ref, sha, tag                                   │
│ status, source, failure_reason                  │
│ merge_request_id, pipeline_schedule_id          │
└─────────────────────────────────────────────────┘
         │                    │
         │1                   │1
         ▼ *                  ▼ *
┌──────────────────┐   ┌───────────────────────┐
│   Ci::Stage      │   │   CommitStatus        │
├──────────────────┤   │   (Ci::Build等)       │
│ id               │   ├───────────────────────┤
│ pipeline_id      │   │ id                    │
│ name             │   │ commit_id (pipeline)  │
│ position         │   │ status                │
│ status           │   │ name, stage           │
└──────────────────┘   └───────────────────────┘
                              │
                              │1
                              ▼ *
                       ┌──────────────────┐
                       │  Ci::JobArtifact │
                       ├──────────────────┤
                       │ id               │
                       │ job_id           │
                       │ file_type        │
                       └──────────────────┘
```

## 3. 処理フロー

### 3.1 パイプライン作成フロー
```
[トリガーイベント]
     │
     │ push / web / schedule / api / merge_request
     ▼
[Ci::CreatePipelineService]
     │
     ├── Chain::Build
     │   └── パイプラインオブジェクト初期化
     │
     ├── Chain::Validate::Abilities
     │   └── 権限チェック (create_pipeline)
     │
     ├── Chain::Validate::Repository
     │   └── リポジトリ存在確認
     │
     ├── Chain::Build::Associations
     │   └── MR, Schedule等の関連付け
     │
     ├── Chain::Limit::RateLimit
     │   └── レートリミットチェック
     │
     ├── Chain::AssignPartition
     │   └── パーティション割り当て
     │
     ├── Chain::Skip
     │   └── [skip ci]チェック
     │
     ├── Chain::Validate::Config
     │   └── .gitlab-ci.yml検証
     │
     ├── Chain::Config::Content
     │   └── 設定ファイル取得
     │
     ├── Chain::Config::Process
     │   └── YAML解析・処理
     │
     ├── Chain::EvaluateWorkflowRules
     │   └── workflowルール評価
     │
     ├── Chain::Seed
     │   └── ジョブシード作成
     │
     ├── Chain::Limit::Size
     │   └── パイプラインサイズ制限
     │
     ├── Chain::Limit::ActiveJobs
     │   └── アクティブジョブ数制限
     │
     ├── Chain::Populate
     │   └── ジョブ・ステージ生成
     │
     ├── Chain::Create
     │   └── データベース保存
     │
     ├── Chain::CancelPendingPipelines
     │   └── 重複パイプラインキャンセル
     │
     └── Chain::Pipeline::Process
         └── パイプライン処理開始
```

### 3.2 パイプライン再実行フロー
```
[ユーザー]
     │
     │ retry
     ▼
[Ci::RetryPipelineService]
     │
     ├── 1. 権限チェック (update_pipeline)
     │
     ├── 2. ensure_scheduling_type!
     │   └── スケジューリングタイプ設定
     │
     ├── 3. 失敗ジョブのクローン
     │   └── Ci::RetryJobService.clone!
     │
     ├── 4. スキップされたジョブの再処理
     │   └── job.process(current_user)
     │
     ├── 5. ソースブリッジのリセット
     │   └── reset_source_bridge!
     │
     ├── 6. ビルド失敗Todoのクローズ
     │   └── AddTodoWhenBuildFailsService.close_all
     │
     └── 7. パイプライン開始
         └── Ci::PipelineCreation::StartPipelineService
```

### 3.3 パイプラインキャンセルフロー
```
[ユーザー]
     │
     │ cancel
     ▼
[Ci::CancelPipelineService]
     │
     ├── 1. 権限チェック (cancel_pipeline)
     │
     ├── 2. キャンセル可能チェック
     │   └── pipeline.cancelable?
     │
     ├── 3. auto_canceled_by設定
     │
     ├── 4. ジョブキャンセル
     │   ├── safe_cancellation: true
     │   │   └── interruptible:trueのジョブのみ
     │   └── safe_cancellation: false
     │       └── 全cancelable_statuses
     │
     └── 5. 子パイプラインキャンセル（cascade_to_children）
         ├── 同期実行
         └── 非同期実行 (CancelPipelineWorker)
```

## 4. 状態遷移

### 4.1 パイプラインステータス状態図
```
                          ┌──────────────┐
                          │   created    │
                          └──────┬───────┘
                                 │
         ┌───────────────────────┼───────────────────────┐
         │                       │                       │
         ▼                       ▼                       ▼
┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│waiting_for_     │    │   preparing     │    │    pending      │
│resource         │    │                 │    │                 │
└────────┬────────┘    └────────┬────────┘    └────────┬────────┘
         │                      │                      │
         └──────────────────────┴──────────────────────┘
                                 │
                                 ▼
                        ┌─────────────────┐
                        │    running      │
                        └────────┬────────┘
                                 │
         ┌───────────────────────┼───────────────────────┐
         │                       │                       │
         ▼                       ▼                       ▼
┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│    success      │    │     failed      │    │   canceling     │
└─────────────────┘    └─────────────────┘    └────────┬────────┘
                                                       │
                                                       ▼
                                              ┌─────────────────┐
                                              │    canceled     │
                                              └─────────────────┘

[manual / scheduled / skipped は別系統で発生]
```

### 4.2 状態遷移後処理
| 遷移 | 後処理 |
|------|--------|
| any -> running | PipelineMetricsWorker実行 |
| any -> success | PipelineMetricsWorker、DailyBuildGroupReportResultsWorker実行 |
| any -> completed | PipelineFinishedWorker、UnlockPreviousPipelinesWorker実行 |
| any -> success/failed | PipelineNotificationWorker実行、ci_ref更新 |
| any -> failed | AutoDevops::DisableWorker実行（auto_devops時） |

## 5. ビジネスルール

### 5.1 パイプライン作成の制約
| ルールID | ルール | 実装箇所 |
|----------|--------|----------|
| PI-R01 | sha, ref, statusは必須 | pipeline.rb:177-185 |
| PI-R02 | refは最大300文字 | MAX_REF_LENGTH = 300 |
| PI-R03 | shaは最大64文字 | MAX_SHA_LENGTH = 64 |
| PI-R04 | yaml_errorsは最大100KB | YAML_ERRORS_MAX_LENGTH |
| PI-R05 | マージリクエストパイプラインはタグ不可 | validates :tag, inclusion: { in: [false], if: :merge_request? } |
| PI-R06 | 00000000のshaは不可（ブランチ削除） | valid_commit_sha |

### 5.2 パイプライン操作の権限
| 操作 | 必要権限 | 説明 |
|------|----------|------|
| 一覧表示 | read_pipeline, read_build | プロジェクトメンバー |
| 詳細表示 | read_pipeline, read_build | プロジェクトメンバー |
| 作成 | create_pipeline | Developer以上 |
| 再実行 | update_pipeline | Developer以上 |
| キャンセル | cancel_pipeline | Developer以上 |
| 削除 | destroy_pipeline | Maintainer以上 |

### 5.3 キャンセル可能条件
```ruby
CANCELABLE_STATUSES = [:created, :waiting_for_resource, :preparing, :pending, :running, :waiting_for_callback, :scheduled]

def cancelable?
  CANCELABLE_STATUSES.include?(self.status) && internal_pipeline?
end
```

### 5.4 アーカイブ条件
```ruby
def archived?
  archive_builds_older_than = Gitlab::CurrentSettings.archive_builds_older_than
  archive_builds_older_than.present? && created_at < archive_builds_older_than
end
```

## 6. セキュリティ・権限

### 6.1 保護されたパイプライン
```ruby
def protected_ref?
  merge_request? ? protected_for_merge_request? : project.protected_for?(git_ref)
end
```

### 6.2 MRパイプラインの保護
- MRパイプラインの保護変数公開条件：
  1. マージリクエストref使用
  2. プロジェクトで`protect_merge_request_pipelines`有効
  3. ソースとターゲットが同一プロジェクト
  4. ユーザーがソースブランチを更新可能
  5. ユーザーがターゲットブランチを更新可能
  6. 両ブランチが保護されている

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

### 7.1 読み解く順序
1. **モデル層**: Ci::Pipeline（状態機械、関連）
2. **サービス層**: CreatePipelineService（Chainシーケンス）
3. **コントローラー層**: PipelinesController
4. **Finder**: PipelinesFinder

### 7.2 プログラム呼び出し階層図
```
Ci::CreatePipelineService
├── Gitlab::Ci::Pipeline::Chain::Sequence
│   ├── Chain::Build
│   ├── Chain::Validate::Abilities
│   ├── Chain::Validate::Repository
│   ├── Chain::Validate::Config
│   ├── Chain::Config::Content
│   ├── Chain::Config::Process
│   ├── Chain::EvaluateWorkflowRules
│   ├── Chain::Seed
│   ├── Chain::Limit::Size
│   ├── Chain::Populate
│   ├── Chain::Create
│   ├── Chain::CancelPendingPipelines
│   └── Chain::Pipeline::Process
├── Ci::PipelineCreatedEvent (EventStore)
└── ServiceResponse

Ci::RetryPipelineService
├── Ci::RetryJobService
│   └── clone!
├── MergeRequests::AddTodoWhenBuildFailsService
└── Ci::PipelineCreation::StartPipelineService

Ci::CancelPipelineService
├── cancel_jobs (each_batch)
└── Ci::CancelPipelineWorker (async children)
```

### 7.3 データフロー図
```
[.gitlab-ci.yml]
       │
       ▼
[Chain::Config::Content]
       │
       ▼
[Chain::Config::Process]
       │
       ├── Gitlab::Ci::YamlProcessor
       │
       ▼
[Chain::Seed]
       │
       ├── stages定義
       ├── jobs定義
       └── variables定義
       │
       ▼
[Chain::Populate]
       │
       ├── Ci::Stage作成
       └── Ci::Build/Ci::Bridge作成
       │
       ▼
[Chain::Create]
       │
       └── DB保存
       │
       ▼
[Chain::Pipeline::Process]
       │
       └── Ci::PipelineCreation::StartPipelineService
           └── ジョブ実行開始
```

### 7.4 関連ファイル一覧
| ファイルパス | 責務 |
|--------------|------|
| `app/models/ci/pipeline.rb` | パイプラインモデル |
| `app/controllers/projects/pipelines_controller.rb` | コントローラー |
| `app/services/ci/create_pipeline_service.rb` | 作成サービス |
| `app/services/ci/retry_pipeline_service.rb` | 再実行サービス |
| `app/services/ci/cancel_pipeline_service.rb` | キャンセルサービス |
| `app/services/ci/destroy_pipeline_service.rb` | 削除サービス |
| `app/finders/ci/pipelines_finder.rb` | 検索Finder |
| `lib/gitlab/ci/pipeline/chain/*.rb` | 作成チェーン各ステップ |
| `app/workers/ci/pipeline_finished_worker.rb` | 完了後処理Worker |
| `app/workers/pipeline_hooks_worker.rb` | Webhookトリガー |
| `app/workers/pipeline_notification_worker.rb` | 通知Worker |

## 8. 拡張ポイント

### 8.1 EE拡張
- **マージトレインパイプライン**: merge_train_pipeline?
- **セキュリティオーケストレーションポリシー**: source: :security_orchestration_policy
- **パイプライン実行ポリシー**: Chain::PipelineExecutionPolicies

### 8.2 Chain追加手順
1. `lib/gitlab/ci/pipeline/chain/`に新Chainクラス追加
2. `Ci::CreatePipelineService::SEQUENCE`に追加
3. 必要に応じてCommandにオプション追加

### 8.3 新規ソース追加手順
1. `Enums::Ci::Pipeline.sources`に追加
2. 対応するトリガーサービス/Workerを実装
3. 必要に応じてChainで条件分岐追加
