# 機能設計書 28-マージリクエスト作成

## 概要

本ドキュメントは、GitLabにおけるマージリクエスト作成機能の設計を定義する。コード変更のレビュー・マージ依頼を作成し、チーム内でのコラボレーションを促進する機能である。

### 本機能の処理概要

マージリクエスト作成機能は、ソースブランチの変更をターゲットブランチにマージするための依頼を作成する機能である。

**業務上の目的・背景**：現代のソフトウェア開発では、直接本番ブランチに変更をプッシュするのではなく、マージリクエスト（プルリクエスト）を通じたコードレビューが標準的なプラクティスである。本機能により、変更内容の可視化、レビュープロセスの管理、CI/CDパイプラインとの連携、承認フローの実行が可能となり、コード品質とチームコラボレーションが向上する。

**機能の利用シーン**：
- 新機能の実装完了後、レビュー依頼を作成する
- バグ修正をレビューしてもらうためにMRを作成する
- フィーチャーブランチをdevelopブランチにマージする
- フォークしたリポジトリから本家へ変更を提案する
- ドキュメント更新のレビューを依頼する

**主要な処理内容**：
1. ソースブランチとターゲットブランチの選択
2. タイトル・説明の入力（テンプレート対応）
3. 担当者・レビュアーの設定
4. ラベル・マイルストーンの設定
5. Draft（下書き）状態の設定
6. スカッシュマージ設定のデフォルト適用
7. マージリクエストの保存と通知

**関連システム・外部連携**：CI/CDパイプライン（MR作成時に自動実行）、通知システム、Sidekiqワーカー

**権限による制御**：ソースプロジェクトでの create_merge_request_from 権限、ターゲットプロジェクトでの create_merge_request_in 権限が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 61 | MR一覧 | 主機能 | マージリクエストの一覧表示 |
| 62 | MR新規作成 | 主機能 | 新規マージリクエストの作成 |

## 機能種別

CRUD操作（CREATE）+ 非同期処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| source_branch | String | Yes | ソースブランチ名 | 存在するブランチ |
| target_branch | String | Yes | ターゲットブランチ名 | 存在するブランチ |
| target_project_id | Integer | No | ターゲットプロジェクトID | フォーク元プロジェクト |
| title | String | Yes | MRタイトル | 空でない文字列 |
| description | String | No | MR説明 | - |
| assignee_ids | Array<Integer> | No | 担当者IDリスト | 有効なユーザーID |
| reviewer_ids | Array<Integer> | No | レビュアーIDリスト | 有効なユーザーID |
| label_ids | Array<Integer> | No | ラベルIDリスト | 有効なラベルID |
| milestone_id | Integer | No | マイルストーンID | 有効なマイルストーンID |
| squash | Boolean | No | スカッシュマージフラグ | true/false |
| merge_after | DateTime | No | マージスケジュール | 将来の日時 |

### 入力データソース

- URL パス: `/project_namespace/project_name/-/merge_requests/new`
- フォーム入力による設定
- テンプレートファイル（.gitlab/merge_request_templates/）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| merge_request | MergeRequest | マージリクエストオブジェクト |
| merge_request.iid | Integer | プロジェクト内ID |
| merge_request.title | String | タイトル |
| merge_request.description | String | 説明 |
| merge_request.source_branch | String | ソースブランチ |
| merge_request.target_branch | String | ターゲットブランチ |
| merge_request.state | String | 状態（opened/closed/merged/locked） |
| merge_request.merge_status | String | マージ可能性ステータス |

### 出力先

- HTML: 作成されたMR詳細ページへリダイレクト
- JSON: API レスポンス

## 処理フロー

### 処理シーケンス

```
1. リクエスト受信・認証確認
   └─ 権限チェック（source/target両方）
2. プロジェクト設定の取得
   └─ set_projects! でソース/ターゲット確定
3. デフォルト値の設定
   └─ set_default_attributes!（squash設定など）
4. MRオブジェクトの生成
   └─ MergeRequest.new
5. バリデーション
   └─ before_create でスパムチェック等
6. MRの保存
   └─ create メソッド
7. 後処理
   └─ after_create でワーカー起動、preparing状態に
8. レスポンス出力
   └─ MR詳細ページへリダイレクト
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{ソースプロジェクト権限?}
    B -->|No| C[アクセス拒否]
    B -->|Yes| D{ターゲットプロジェクト権限?}
    D -->|No| C
    D -->|Yes| E[デフォルト値設定]
    E --> F[MRオブジェクト生成]
    F --> G[スパムチェック]
    G --> H{バリデーション成功?}
    H -->|No| I[エラー表示]
    H -->|Yes| J[MR保存]
    J --> K[preparing状態に]
    K --> L[Workerエンキュー]
    L --> M[MR詳細へリダイレクト]
    I --> N[終了]
    M --> N
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-28-01 | スカッシュデフォルト | プロジェクト設定に基づくスカッシュデフォルト | 常時 |
| BR-28-02 | Draft設定 | タイトルに Draft: または WIP: 付与で下書き状態 | 常時 |
| BR-28-03 | 権限チェック | ソース・ターゲット両プロジェクトへの権限必要 | 常時 |
| BR-28-04 | iid自動採番 | プロジェクト内で一意のiidを自動採番 | 常時 |
| BR-28-05 | preparing状態 | 作成直後はpreparing状態、差分計算後に遷移 | 常時 |

### 計算ロジック

**iid採番**：
- プロジェクト内で最大のiid + 1を割り当て
- AtomicInternalId による競合回避

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 作成 | merge_requests | INSERT | MRレコード作成 |
| 作成 | merge_request_assignees | INSERT | 担当者関連 |
| 作成 | merge_request_reviewers | INSERT | レビュアー関連 |
| 作成 | merge_request_diffs | INSERT | 差分情報（非同期） |
| 作成 | merge_request_metrics | INSERT | メトリクス情報 |

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

#### merge_requests

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | title, description, source_branch, target_branch, source_project_id, target_project_id, author_id, state_id, squash | フォーム入力値 | - |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 403 | Forbidden | 権限不足 | アクセス拒否 |
| 422 | UnprocessableEntity | バリデーションエラー | エラーメッセージ表示 |
| Spam | SpamDetected | スパム判定 | CAPTCHA表示 |

### リトライ仕様

特になし

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

MR作成と関連レコード（担当者、レビュアー等）の挿入はトランザクション内で実行

## パフォーマンス要件

- 差分計算は非同期（NewMergeRequestWorker）
- preparing状態で即座にレスポンス返却

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

- 権限チェック（ソース/ターゲット両方）
- スパムチェック（check_for_spam）
- XSS対策（タイトル・説明のサニタイズ）

## 備考

- MR作成後、CI/CDパイプラインが自動起動（設定による）
- メール/Web通知が担当者・レビュアーに送信

---

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

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

### 推奨読解順序

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

マージリクエストのデータモデルを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | merge_request.rb | `app/models/merge_request.rb` | MRモデル、状態遷移、関連 |

**読解のコツ**: state_machine による状態遷移、merge_status の遷移、各種関連（assignees, reviewers, diffs）を理解する。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | merge_requests_controller.rb | `app/controllers/projects/merge_requests_controller.rb` | コントローラー実装 |

**主要処理フロー**:
1. **97-104行目**: index - MR一覧表示
2. new/create アクションは IssuableActions concern で定義

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | create_service.rb | `app/services/merge_requests/create_service.rb` | 作成サービス |
| 3-2 | base_service.rb | `app/services/merge_requests/base_service.rb` | 基底サービス |

**主要処理フロー**:
- **5-21行目**: execute - 作成処理のメインロジック
- **23-36行目**: after_create - 後処理（Worker起動、preparing状態）
- **45-53行目**: before_create - 事前処理（スパムチェック）
- **55-73行目**: set_projects! - プロジェクト設定

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

```
MergeRequestsController#create
    │
    ├─ authorize_create_merge_request!
    │
    └─ CreateService#execute
           ├─ set_projects!
           │      └─ ソース/ターゲットプロジェクト設定
           ├─ set_default_attributes!
           │      └─ スカッシュデフォルト設定
           ├─ before_create
           │      └─ check_for_spam
           ├─ MergeRequest#save
           │      └─ ensure_merge_request_diff（スキップ）
           └─ after_create
                  ├─ invalidate_all_users_cache_count
                  ├─ NewMergeRequestWorker（非同期）
                  └─ mark_as_preparing
```

### データフロー図

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

フォーム入力       ───▶  MergeRequestsController   ───▶  リダイレクト
(title, branches等)      │
                         ▼
                    CreateService
                         │
                         ▼
                    MergeRequest.save ────────────────▶  DB INSERT
                         │
                         ▼
                    NewMergeRequestWorker ────────────▶  非同期処理
                         │                               (差分計算、通知)
                         ▼
                    MR詳細ページ
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| merge_requests_controller.rb | `app/controllers/projects/merge_requests_controller.rb` | コントローラー | MRのエントリーポイント |
| create_service.rb | `app/services/merge_requests/create_service.rb` | サービス | 作成サービス |
| base_service.rb | `app/services/merge_requests/base_service.rb` | サービス | 基底サービス |
| merge_request.rb | `app/models/merge_request.rb` | モデル | MRモデル |
| after_create_service.rb | `app/services/merge_requests/after_create_service.rb` | サービス | 作成後処理 |
| new_merge_request_worker.rb | `app/workers/new_merge_request_worker.rb` | ワーカー | 非同期処理 |
| issuable_actions.rb | `app/controllers/concerns/issuable_actions.rb` | Concern | CRUD共通処理 |
| new.html.haml | `app/views/projects/merge_requests/new.html.haml` | ビュー | 作成フォーム |
