# 画面設計書 62-MR新規作成

## 概要

本ドキュメントは、GitLabプロジェクトのマージリクエスト新規作成画面の設計仕様を定義するものである。

### 本画面の処理概要

本画面は、新しいマージリクエスト（MR）を作成するための画面であり、ソースブランチからターゲットブランチへのコード変更をマージするためのリクエストを起票する機能を提供する。開発者がコード変更をレビュー依頼し、メインブランチへの統合を行うためのワークフローの起点となる重要な画面である。

**業務上の目的・背景**：ソフトウェア開発において、個別の機能開発やバグ修正はブランチで行われ、それをメインブランチにマージする際にはコードレビューが必要である。マージリクエストは、変更内容の説明、差分の確認、レビュアーの指定、関連する課題との紐付けなど、レビュープロセスに必要な情報を一元管理する仕組みである。本画面はその作成起点として、必要な情報を効率的に入力できる環境を提供する。

**画面へのアクセス方法**：
1. プロジェクトのMR一覧画面から「New merge request」ボタンをクリック
2. ブランチ一覧画面からブランチを選択し「Create merge request」をクリック
3. Git push後にコンソールに表示されるリンクをクリック
4. Web IDEでコミット後に「Create merge request」を選択
5. URLに直接`/-/merge_requests/new`を入力

**主要な操作・処理内容**：
1. ソースブランチとターゲットブランチの選択/確認
2. MRタイトルと説明の入力（テンプレート適用可能）
3. アサイニーとレビュアーの指定
4. ラベルとマイルストーンの設定
5. マージオプションの設定（squash、ソースブランチ削除）
6. 差分のプレビュー確認
7. 関連パイプラインの確認
8. MR作成の実行

**画面遷移**：
- 遷移元：MR一覧画面、ブランチ一覧、Web IDE、課題詳細画面
- 遷移先：作成したMRの詳細画面、ブランチ選択画面（変更時）

**権限による表示制御**：
- 作成権限（Developer以上）：MR作成機能の利用
- フォークからの作成：Guest以上でフォーク元への作成が可能（設定による）
- ターゲットプロジェクト選択：フォーク関係にあるプロジェクトのみ表示

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 28 | マージリクエスト作成 | 主機能 | 新規マージリクエストの作成処理 |
| 149 | イシュー/MRテンプレート | 補助機能 | MRテンプレートの適用 |

## 画面種別

登録

## URL/ルーティング

| メソッド | URL | アクション | 説明 |
|----------|-----|-----------|------|
| GET | `/:namespace_id/:project_id/-/merge_requests/new` | new | MR新規作成画面表示 |
| POST | `/:namespace_id/:project_id/-/merge_requests` | create | MR作成処理 |
| GET | `/:namespace_id/:project_id/-/merge_requests/new/diffs` | diffs | 差分取得（AJAX） |
| GET | `/:namespace_id/:project_id/-/merge_requests/new/pipelines` | pipelines | パイプライン取得（AJAX） |
| GET | `/:namespace_id/:project_id/-/merge_requests/new/branch_from` | branch_from | ソースブランチ選択 |
| GET | `/:namespace_id/:project_id/-/merge_requests/new/branch_to` | branch_to | ターゲットブランチ選択 |

## 入出力項目

### 入力項目

| 項目名 | データ型 | 必須 | バリデーション | 説明 |
|--------|---------|------|---------------|------|
| source_project_id | integer | ○ | 存在するプロジェクト | ソースプロジェクトID |
| source_branch | string | ○ | 存在するブランチ | ソースブランチ名 |
| target_project_id | integer | ○ | 存在するプロジェクト | ターゲットプロジェクトID |
| target_branch | string | ○ | 存在するブランチ | ターゲットブランチ名 |
| title | string | ○ | 最大255文字 | MRタイトル |
| description | text | - | 最大1MB | MR説明文（Markdown対応） |
| assignee_ids | integer[] | - | 存在するユーザー | アサイニーのユーザーID |
| reviewer_ids | integer[] | - | 存在するユーザー | レビュアーのユーザーID |
| label_ids | integer[] | - | 存在するラベル | ラベルID |
| milestone_id | integer | - | 存在するマイルストーン | マイルストーンID |
| squash | boolean | - | - | squashマージを有効化 |
| remove_source_branch | boolean | - | - | マージ後ソースブランチ削除 |
| draft | boolean | - | - | Draft状態で作成 |

### パラメータ（URL/クエリ）

| パラメータ名 | 説明 |
|-------------|------|
| merge_request[source_branch] | 事前選択するソースブランチ |
| merge_request[target_branch] | 事前選択するターゲットブランチ |
| change_branches | ブランチ変更モード |
| nav_source | 遷移元（webide等） |

## 表示項目

| 項目名 | データ型 | 説明 |
|--------|---------|------|
| ソースプロジェクト | string | マージ元プロジェクト名 |
| ソースブランチ | string | マージ元ブランチ名 |
| ターゲットプロジェクト | string | マージ先プロジェクト名 |
| ターゲットブランチ | string | マージ先ブランチ名 |
| コミット一覧 | object[] | マージ対象のコミット |
| 差分 | object[] | ファイル差分 |
| パイプライン状態 | object | 最新パイプラインの状態 |
| 既存MR警告 | string | 同一ブランチ間の既存MRがある場合の警告 |

## イベント仕様

### 1-ブランチ変更

「Change branches」リンクをクリックすると、ブランチ選択画面が表示される。ソースブランチまたはターゲットブランチを変更し、「Compare branches and continue」をクリックすると、新しいブランチ組み合わせで差分が再計算される。

### 2-フォーム入力

タイトルはソースブランチ名またはコミットメッセージから自動生成される。説明欄ではMRテンプレートを選択適用でき、Markdownプレビューが可能。

### 3-差分タブ表示

「Changes」タブをクリックすると、AJAXでdiffsエンドポイントから差分情報を取得し表示する。ファイル単位での展開/折りたたみが可能。

### 4-パイプラインタブ表示

「Pipelines」タブをクリックすると、ソースブランチの最新パイプライン情報を取得し表示する。ポーリング間隔は10秒。

### 5-MR作成ボタン押下

「Create merge request」ボタンをクリックすると、入力内容のバリデーションが行われ、問題がなければPOSTリクエストでMRが作成される。作成成功時は詳細画面に遷移し、失敗時はエラーメッセージが表示される。

### 6-Draft MR作成

「Create draft merge request」ボタンまたはタイトルに「Draft:」プレフィックスを付けることで、Draft状態のMRを作成できる。

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| MR作成 | merge_requests | INSERT | MRレコードの作成 |
| MR作成 | merge_request_diffs | INSERT | 差分情報の保存 |
| MR作成 | merge_request_diff_files | INSERT | 差分ファイル情報 |
| MR作成 | merge_request_diff_commits | INSERT | 差分コミット情報 |
| アサイン | merge_request_assignees | INSERT | アサイニー関連付け |
| レビュアー設定 | merge_request_reviewers | INSERT | レビュアー関連付け |
| ラベル付与 | label_links | INSERT | ラベル関連付け |
| マイルストーン設定 | merge_requests | UPDATE | milestone_idの設定 |

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

#### merge_requests

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | iid | プロジェクト内連番 | 自動採番 |
| INSERT | title | フォーム入力値 | 必須 |
| INSERT | description | フォーム入力値 | |
| INSERT | source_project_id | 選択されたプロジェクトID | |
| INSERT | source_branch | 選択されたブランチ名 | |
| INSERT | target_project_id | 選択されたプロジェクトID | |
| INSERT | target_branch | 選択されたブランチ名 | |
| INSERT | author_id | 現在のユーザーID | |
| INSERT | state_id | 1 (opened) | |
| INSERT | draft | Draft状態フラグ | |
| INSERT | squash | squash設定 | |
| INSERT | milestone_id | 選択されたマイルストーンID | |
| INSERT | created_at | 現在時刻 | |
| INSERT | updated_at | 現在時刻 | |

## メッセージ仕様

| 種別 | メッセージ | 表示条件 |
|------|----------|---------|
| 警告 | These branches already have an open merge request: {link}. Select a different source or target branch. | 同一ブランチ間に既存MRがある場合 |
| エラー | Title can't be blank | タイトル未入力 |
| エラー | Branch not found | 指定ブランチが存在しない |
| エラー | Source branch and target branch cannot be the same | 同一ブランチを指定 |
| エラー | You don't have permission to create merge request in this project | 作成権限がない場合 |
| 情報 | No commits between {source} and {target} | 差分がない場合 |

## 例外処理

| 例外状況 | 処理内容 |
|---------|---------|
| ソースブランチが削除された | エラーメッセージを表示 |
| ターゲットブランチが削除された | エラーメッセージを表示 |
| フォーク関係が解消された | アクセス拒否 |
| バリデーションエラー | フォーム再表示とエラーメッセージ表示 |
| 権限不足 | 403エラーページを表示 |

## 備考

- Web IDEから作成された場合、イベントトラッキングが行われる
- Git push後のリンクからアクセスした場合も別途トラッキング
- RapidDiffsコンポーネントで高速な差分表示を実現
- MRテンプレートは`.gitlab/merge_request_templates/`ディレクトリに配置

---

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

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

### 推奨読解順序

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

まず、マージリクエスト作成に必要なデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | merge_request.rb | `app/models/merge_request.rb` | MRモデルの属性・バリデーション |
| 1-2 | merge_request_diff.rb | `app/models/merge_request_diff.rb` | 差分管理の仕組み |

**読解のコツ**: `belongs_to`と`has_many`の関連、バリデーションルールに注目する。

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

処理の起点となるコントローラーを特定する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | creations_controller.rb | `app/controllers/projects/merge_requests/creations_controller.rb` | newアクションとcreateアクション |

**主要処理フロー**:
1. **行34-49**: `new`アクション - 変数定義とRapidDiffsプレゼンター設定
2. **行51-67**: `create`アクション - MergeRequests::CreateService呼び出し
3. **行128-151**: `define_new_vars` - フォーム表示用変数の設定

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

MR作成のビジネスロジックを理解する。

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

**主要処理フロー**:
- `execute`メソッドでMRインスタンス作成
- バリデーション実行
- 差分計算の開始
- 通知送信

#### Step 4: ビュー層を理解する

画面表示の仕組みを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | new.html.haml | `app/views/projects/merge_requests/creations/new.html.haml` | メインビュー |
| 4-2 | _page.html.haml | `app/views/projects/merge_requests/creations/_page.html.haml` | ページレイアウト（行1-19） |
| 4-3 | _new_submit.html.haml | `app/views/projects/merge_requests/creations/_new_submit.html.haml` | フォーム表示 |
| 4-4 | _new_compare.html.haml | `app/views/projects/merge_requests/creations/_new_compare.html.haml` | ブランチ比較表示 |

**主要処理フロー**:
- **行8**: 既存MRの競合チェック
- **行10-12**: 作成可能な場合はフォーム表示
- **行14-18**: 競合がある場合は警告表示とブランチ変更画面

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

```
HTTP Request (GET /project/-/merge_requests/new)
    │
    ├─ CreationsController#new
    │      │
    │      ├─ before_action :authorize_create_merge_request_from!
    │      │
    │      ├─ before_action :build_merge_request
    │      │      └─ MergeRequest.new with params
    │      │
    │      └─ define_new_vars
    │             ├─ recent_commits取得
    │             ├─ labels取得
    │             └─ set_pipeline_variables
    │
    └─ render 'new' → _page.html.haml
                            │
                            ├─ can_be_created? チェック
                            │      │
                            │      ├─ Yes → _new_submit.html.haml
                            │      │
                            │      └─ No → _new_compare.html.haml
                            │
                            └─ RapidDiffsコンポーネント

HTTP Request (POST /project/-/merge_requests)
    │
    ├─ CreationsController#create
    │      │
    │      └─ MergeRequests::CreateService#execute
    │             ├─ MergeRequest作成
    │             ├─ MergeRequestDiff作成
    │             ├─ アサイニー/レビュアー設定
    │             ├─ ラベル/マイルストーン設定
    │             └─ 通知送信
    │
    └─ redirect_to MR詳細 or render :new
```

### データフロー図

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

ブランチ選択 ──────▶ CreationsController ──────▶ MR作成フォーム
                          │
                          ├─ build_merge_request
                          │      └─ MR.new
                          │
                          └─ define_new_vars
                                 ├─ コミット一覧
                                 └─ ラベル一覧
                                            │
                                            ▼
フォーム送信 ──────▶ CreateService#execute ──────▶ MRレコード
                          │
                          ├─ バリデーション
                          ├─ DB保存
                          └─ 差分計算開始
                                            │
                                            ▼
                          ──────────────▶ MR詳細画面
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| creations_controller.rb | `app/controllers/projects/merge_requests/creations_controller.rb` | コントローラー | リクエストハンドリング |
| new.html.haml | `app/views/projects/merge_requests/creations/new.html.haml` | ビュー | メインビュー |
| _page.html.haml | `app/views/projects/merge_requests/creations/_page.html.haml` | パーシャル | レイアウト制御 |
| _new_submit.html.haml | `app/views/projects/merge_requests/creations/_new_submit.html.haml` | パーシャル | 送信フォーム |
| _new_compare.html.haml | `app/views/projects/merge_requests/creations/_new_compare.html.haml` | パーシャル | ブランチ比較 |
| create_service.rb | `app/services/merge_requests/create_service.rb` | サービス | 作成ロジック |
| merge_request.rb | `app/models/merge_request.rb` | モデル | データモデル |
| merge_requests.rb | `config/routes/merge_requests.rb` | ルーティング | URL定義 |
| RapidDiffs::MergeRequestCreationPresenter | `app/presenters/rapid_diffs/merge_request_creation_presenter.rb` | プレゼンター | 差分表示用 |
