# 画面設計書 72-パイプラインスケジュール新規作成

## 概要

本ドキュメントは、GitLabのCI/CDパイプラインスケジュール新規作成画面の設計を記述したものである。

### 本画面の処理概要

**業務上の目的・背景**：パイプラインスケジュール新規作成画面は、CI/CDパイプラインの定期実行スケジュールを新規に設定するための画面である。開発チームが夜間ビルド、週次テスト、定期的なセキュリティスキャンなど、特定の間隔でパイプラインを自動実行したい場合にスケジュールを作成する。cron形式での柔軟なスケジュール設定、対象ブランチ/タグの選択、実行時に渡す変数の設定が可能である。

**画面へのアクセス方法**：パイプラインスケジュール一覧画面の「New schedule」ボタンをクリック、またはURL直接アクセス（`/:namespace/:project/-/pipeline_schedules/new`）によりアクセスする。

**主要な操作・処理内容**：
1. スケジュールの説明（Description）の入力
2. cron式によるスケジュール間隔の設定（プリセットまたはカスタム）
3. タイムゾーンの選択
4. 対象ブランチまたはタグの選択
5. スケジュール変数の追加・編集・削除
6. パイプライン入力値（inputs）の設定
7. アクティブ/非アクティブ状態の設定
8. スケジュールの保存

**画面遷移**：
- 遷移元：パイプラインスケジュール一覧画面
- 遷移先：パイプラインスケジュール一覧画面（保存成功時）、エラー時は同画面に留まる

**権限による表示制御**：
- `create_pipeline_schedule`権限がない場合はアクセス不可（403エラー）
- `set_pipeline_variables`権限がない場合は変数設定セクションが非表示
- パイプラインエディタへのリンクは`can_view_pipeline_editor`で制御

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 49 | パイプラインスケジュール | 主機能 | 新規スケジュールの作成 |
| 50 | CI変数管理 | 補助機能 | スケジュール変数の設定 |

## 画面種別

登録

## URL/ルーティング

| パス | HTTPメソッド | アクション |
|------|-------------|-----------|
| `/:namespace/:project/-/pipeline_schedules/new` | GET | new |
| `/:namespace/:project/-/pipeline_schedules` | POST | create |

## 入出力項目

### 入力フォーム

| 項目名 | 必須 | 型 | 説明 | バリデーション |
|--------|------|-----|------|----------------|
| description | 必須 | string | スケジュールの説明 | 必須、最大255文字 |
| cron | 必須 | string | cron形式のスケジュール式 | cron形式バリデーション |
| cron_timezone | 必須 | string | タイムゾーン | 有効なタイムゾーン |
| ref | 必須 | string | 対象ブランチまたはタグ | 必須、存在するref |
| active | 任意 | boolean | アクティブ状態（デフォルト: true） | - |
| variables_attributes | 任意 | array | スケジュール変数 | ネスト属性、重複キー不可 |
| inputs_attributes | 任意 | array | パイプライン入力値 | 最大50件 |

### 変数（variables_attributes）

| 項目名 | 必須 | 型 | 説明 |
|--------|------|-----|------|
| variable_type | 必須 | string | 変数タイプ（env_var/file） |
| key | 必須 | string | 変数キー |
| secret_value | 必須 | string | 変数値（マスク可能） |

### 入力値（inputs_attributes）

| 項目名 | 必須 | 型 | 説明 |
|--------|------|-----|------|
| name | 必須 | string | 入力値名 |
| value | 必須 | string | 入力値 |

## 表示項目

### フォームセクション

| セクション | 項目 | 説明 |
|-----------|------|------|
| 基本情報 | Description | スケジュールの説明入力フィールド |
| スケジュール設定 | Interval Pattern | プリセット選択またはカスタムcron入力 |
| スケジュール設定 | Cron timezone | タイムゾーンドロップダウン |
| ターゲット | Target branch or tag | ブランチ/タグ選択（RefSelector） |
| 変数 | Variables | キー・値・タイプの入力フォーム（複数行） |
| 入力値 | Inputs | CI/CD入力値のフォーム |
| 状態 | Activated | アクティブ状態のチェックボックス |

### プリセット間隔オプション

| オプション | cron式 | 説明 |
|-----------|--------|------|
| Every day (at 4:00am) | `0 4 * * *` | 毎日午前4時 |
| Every week (Sundays at 4:00am) | `0 4 * * 0` | 毎週日曜午前4時 |
| Every month (on the 1st at 4:00am) | `0 4 1 * *` | 毎月1日午前4時 |
| Custom | ユーザー入力 | カスタムcron式 |

## イベント仕様

### 1-フォーム送信（保存）

**処理内容**：入力された情報を元に新規パイプラインスケジュールを作成する。

**処理フロー**：
1. フォームバリデーション実行
2. GraphQL `createPipelineScheduleMutation`を実行
3. 成功時：パイプラインスケジュール一覧画面にリダイレクト
4. 失敗時：エラーメッセージを表示し、フォームに留まる

### 2-間隔パターン選択

**処理内容**：プリセットまたはカスタムの間隔パターンを選択する。

**処理フロー**：
1. ラジオボタンでプリセットを選択
2. 選択に応じてcronフィールドを更新
3. カスタム選択時はcron入力フィールドが編集可能に

### 3-ブランチ/タグ選択

**処理内容**：パイプライン実行対象のブランチまたはタグを選択する。

**処理フロー**：
1. RefSelectorコンポーネントでブランチ/タグを検索
2. 選択したrefをフォームに反映
3. デフォルトはプロジェクトのデフォルトブランチ

### 4-変数追加/削除

**処理内容**：スケジュール実行時に渡す変数を追加・削除する。

**処理フロー**：
1. 「Add variable」ボタンで新規行を追加
2. 削除ボタンで行を削除（_destroy: trueをセット）
3. 変数タイプ（env_var/file）を選択

### 5-キャンセル

**処理内容**：入力をキャンセルして一覧画面に戻る。

**処理フロー**：
1. キャンセルボタンクリック
2. パイプラインスケジュール一覧画面にリダイレクト

## データベース更新仕様

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| スケジュール作成 | ci_pipeline_schedules | INSERT | 新規スケジュールレコード作成 |
| 変数追加 | ci_pipeline_schedule_variables | INSERT | スケジュール変数の作成 |
| 入力値追加 | ci_pipeline_schedule_inputs | INSERT | パイプライン入力値の作成 |

### テーブル別更新項目詳細

#### ci_pipeline_schedules

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | project_id | 現在のプロジェクトID | 必須 |
| INSERT | owner_id | 現在のユーザーID | 作成者が所有者になる |
| INSERT | description | フォーム入力値 | 必須 |
| INSERT | cron | フォーム入力値 | cron形式 |
| INSERT | cron_timezone | フォーム入力値 | タイムゾーン名 |
| INSERT | ref | フォーム入力値 | ブランチ/タグ名 |
| INSERT | active | フォーム入力値（デフォルトtrue） | boolean |
| INSERT | next_run_at | 自動計算 | cron式から次回実行時刻を計算 |
| INSERT | created_at | 現在時刻 | 自動設定 |
| INSERT | updated_at | 現在時刻 | 自動設定 |

#### ci_pipeline_schedule_variables

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | pipeline_schedule_id | 作成したスケジュールID | 外部キー |
| INSERT | key | フォーム入力値 | 変数キー |
| INSERT | value | フォーム入力値（暗号化） | 変数値 |
| INSERT | variable_type | フォーム入力値 | env_var or file |

## メッセージ仕様

| 種別 | メッセージ | 表示条件 |
|------|----------|---------|
| 成功 | Schedule created successfully | 作成成功時（一覧画面にリダイレクト） |
| エラー | The current user is not authorized to create the pipeline schedule | 権限不足時 |
| エラー | Cron is invalid | cron形式が不正な場合 |
| エラー | Cron timezone is invalid | タイムゾーンが不正な場合 |
| エラー | Ref can't be blank | ブランチ/タグ未選択時 |
| エラー | Description can't be blank | 説明未入力時 |
| エラー | Variables have duplicate keys | 変数キーが重複している場合 |
| 情報 | You can schedule pipelines to run up to {daily_limit} times per day | 日次制限の表示 |

## 例外処理

| 例外状況 | 処理内容 |
|---------|---------|
| 権限不足 | 403 Forbiddenを返し、アクセス拒否画面にリダイレクト |
| バリデーションエラー | エラーメッセージを表示し、フォームを再表示 |
| プラン制限超過 | エラーメッセージを表示し、作成を拒否 |
| プロジェクト未検出 | 404 Not Foundを返す |

## 備考

- next_run_atはcronとcron_timezoneから自動計算される
- スケジュールの所有者は作成者に自動設定される
- 変数値は暗号化されてデータベースに保存される
- プラン制限（ci_pipeline_schedules）を超える場合は作成不可
- worker_cron_expressionに基づいてスケジュールワーカーが実行間隔を決定

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | pipeline_schedule.rb | `app/models/ci/pipeline_schedule.rb` | バリデーション（cron, cron_timezone, ref, description）、accepts_nested_attributes_for |
| 1-2 | pipeline_schedule_variable.rb | `app/models/ci/pipeline_schedule_variable.rb` | 変数の構造とバリデーション |

**読解のコツ**: `validates`ディレクティブと`accepts_nested_attributes_for :variables`に注目する。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | pipeline_schedules_controller.rb | `app/controllers/projects/pipeline_schedules_controller.rb` | new/createアクション、schedule_paramsメソッド |
| 2-2 | new.html.haml | `app/views/projects/pipeline_schedules/new.html.haml` | Vueコンポーネントのマウントとデータ属性 |

**主要処理フロー**:
1. **24行目**: newアクションは空のメソッド（ビューのみ）
2. **26-34行目**: createアクションでCreateServiceを呼び出し
3. **97-101行目**: schedule_paramsでStrong Parametersを定義

#### Step 3: サービス層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | create_service.rb | `app/services/ci/pipeline_schedules/create_service.rb` | スケジュール作成のビジネスロジック |
| 3-2 | base_save_service.rb | `app/services/ci/pipeline_schedules/base_save_service.rb` | 共通の保存ロジック |

#### Step 4: フロントエンドコンポーネントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | pipeline_schedules_form.vue | `app/assets/javascripts/ci/pipeline_schedules/components/pipeline_schedules_form.vue` | フォームコンポーネント、バリデーション、GraphQL mutation |
| 4-2 | interval_pattern_input.vue | `app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue` | cron間隔の入力コンポーネント |
| 4-3 | timezone_dropdown.vue | `app/assets/javascripts/vue_shared/components/timezone_dropdown/timezone_dropdown.vue` | タイムゾーン選択 |

**主要処理フロー**:
- **69-130行目**: Apollo queryでスケジュール情報を取得（編集時のみ使用）
- **create_pipeline_schedule.mutation.graphql**: GraphQL mutationの定義

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

```
[ブラウザ] GET /project/-/pipeline_schedules/new
    │
    ├─ PipelineSchedulesController#new
    │      └─ ビューレンダリング
    │
    └─ [Vue.js] pipeline_schedules_form.vue
           │
           ├─ IntervalPatternInput
           │      └─ cron式の入力/プリセット
           │
           ├─ TimezoneDropdown
           │      └─ タイムゾーン選択
           │
           ├─ RefSelector
           │      └─ ブランチ/タグ選択
           │
           └─ VariablesForm
                  └─ 変数入力

[フォーム送信]
    │
    └─ createPipelineScheduleMutation (GraphQL)
           │
           └─ Mutations::Ci::PipelineSchedule::Create
                  │
                  └─ Ci::PipelineSchedules::CreateService#execute
                         │
                         ├─ 権限チェック
                         ├─ バリデーション
                         └─ PipelineSchedule#save
```

### データフロー図

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

フォーム入力 ─────────────▶ Vue.jsバリデーション ─────────────▶ フォームエラー表示
  (description,                    │
   cron, ref, etc.)                ▼
                           GraphQL Mutation
                                   │
                                   ▼
                           CreateService#execute
                                   │
                           ┌───────┴───────┐
                           │               │
                           ▼               ▼
                      権限チェック    バリデーション
                           │               │
                           └───────┬───────┘
                                   ▼
                           PipelineSchedule.create
                                   │
                                   ▼
                           ┌───────┴───────┐
                           │               │
                           ▼               ▼
                        成功           失敗
                           │               │
                           ▼               ▼
                    一覧へリダイレクト   エラー表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| pipeline_schedules_controller.rb | `app/controllers/projects/pipeline_schedules_controller.rb` | コントローラー | new/createアクション |
| new.html.haml | `app/views/projects/pipeline_schedules/new.html.haml` | ビュー | Vueマウントポイント |
| create_service.rb | `app/services/ci/pipeline_schedules/create_service.rb` | サービス | 作成ビジネスロジック |
| pipeline_schedule.rb | `app/models/ci/pipeline_schedule.rb` | モデル | データモデル |
| pipeline_schedules_form.vue | `app/assets/javascripts/ci/pipeline_schedules/components/pipeline_schedules_form.vue` | Vueコンポーネント | 入力フォーム |
| interval_pattern_input.vue | `app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue` | Vueコンポーネント | cron入力 |
| pipeline_schedules_helper.rb | `app/helpers/ci/pipeline_schedules_helper.rb` | ヘルパー | フォームデータ生成 |
| create_pipeline_schedule.mutation.graphql | `app/assets/javascripts/ci/pipeline_schedules/graphql/mutations/create_pipeline_schedule.mutation.graphql` | GraphQL | 作成mutation |
