# 画面設計書 301-一括インポート状態

## 概要

本ドキュメントは、GitLabの一括インポート（Direct Transfer）状態表示画面の設計仕様を定義する。

### 本画面の処理概要

本画面は、別のGitLabインスタンスからグループやプロジェクトを一括インポート（Direct Transfer）する際のインポート元データ選択と、インポート処理の状態を表示するための画面である。

**業務上の目的・背景**：GitLabでは、異なるGitLabインスタンス間でグループ単位のデータ移行が必要になるケースがある。例えば、セルフホストのGitLabからGitLab.comへの移行、あるいは組織統合に伴うインスタンス間のデータ移行などである。本画面は、このような移行作業をユーザー自身が実行し、その進捗状況を確認できるようにすることで、管理者やプロジェクトオーナーの作業負担を軽減する。

**画面へのアクセス方法**：新規グループ作成画面（`/groups/new`）の「Import group」タブから、GitLab Direct Transferオプションを選択し、ソースGitLabのURLとアクセストークンを入力後、設定が完了するとこの画面に遷移する。

**主要な操作・処理内容**：
1. ソースGitLabインスタンスから取得可能なグループ一覧の表示
2. インポートするグループの選択
3. インポート先の名前空間（Namespace）の設定
4. プロジェクト・メンバーシップのインポートオプション設定
5. インポート処理の開始
6. インポート処理の進捗状況のリアルタイム監視

**画面遷移**：
- 遷移元：新規グループ作成画面（Import groupタブ）
- 遷移先：一括インポート履歴画面、新規グループ作成画面

**権限による表示制御**：
- ソースGitLabでOwner権限を持つグループのみがインポート対象として表示される
- インポート先名前空間に対してサブグループ作成権限（`create_subgroup`）が必要

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 110 | バルクインポート | 主機能 | 一括インポート状態表示 |

## 画面種別

一覧・操作画面

## URL/ルーティング

| メソッド | パス | アクション |
|---------|------|----------|
| GET | `/import/bulk_imports/status` | HTML表示 |
| GET | `/import/bulk_imports/status.json` | JSON（インポート可能データ取得） |
| POST | `/import/bulk_imports` | インポート作成 |
| GET | `/import/bulk_imports/realtime_changes.json` | リアルタイム状態更新 |

## 入出力項目

### 入力項目（セッション経由）

| 項目名 | データ型 | 必須 | 説明 |
|--------|---------|------|------|
| bulk_import_gitlab_url | String | Yes | ソースGitLabインスタンスのURL |
| bulk_import_gitlab_access_token | String | Yes | ソースGitLabのアクセストークン |

### 入力項目（クエリパラメータ）

| 項目名 | データ型 | 必須 | 説明 |
|--------|---------|------|------|
| namespace_id | Integer | No | インポート先名前空間ID |
| filter | String | No | グループ名検索フィルター |
| page | Integer | No | ページ番号 |
| per_page | Integer | No | 1ページあたりの件数 |

### 入力項目（インポート作成時）

| 項目名 | データ型 | 必須 | 説明 |
|--------|---------|------|------|
| source_type | String | Yes | ソース種別（`group_entity`固定） |
| source_full_path | String | Yes | ソースグループのフルパス |
| destination_slug | String | Yes | インポート先のスラグ |
| destination_namespace | String | Yes | インポート先の名前空間パス |
| migrate_projects | Boolean | No | プロジェクトも移行するか |
| migrate_memberships | Boolean | No | メンバーシップも移行するか |

## 表示項目

### インポート可能グループ一覧

| 項目名 | データ型 | 説明 |
|--------|---------|------|
| full_path | String | グループのフルパス |
| full_name | String | グループのフル名称 |
| web_url | String | グループのURL |
| destination_namespace | String | インポート先名前空間（入力） |
| destination_slug | String | インポート先スラグ（入力） |

### インポート状態

| 項目名 | データ型 | 説明 |
|--------|---------|------|
| id | Integer | BulkImport ID |
| status_name | String | 状態名（created/started/finished/timeout/failed/canceled） |
| has_failures | Boolean | 失敗があるか |

## イベント仕様

### 1-グループ検索

ユーザーが検索フィールドにテキストを入力すると、`filter`パラメータ付きでAPI（`/import/bulk_imports/status.json`）が呼び出され、検索結果でグループ一覧が更新される。

### 2-インポート開始

「Import」ボタン押下時の処理：
1. `POST /import/bulk_imports` にリクエスト送信
2. `BulkImports::CreateService`が呼び出され、BulkImportレコードが作成される
3. BulkImportエンティティが非同期ワーカーで処理開始
4. 3秒間隔でポーリング（`/import/bulk_imports/realtime_changes.json`）により状態更新

### 3-履歴画面への遷移

「View history」リンククリック時、`/import/bulk_imports/history`へ遷移する。

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| インポート開始 | bulk_imports | INSERT | インポートジョブの親レコード作成 |
| インポート開始 | bulk_import_entities | INSERT | インポート対象エンティティ作成 |
| インポート開始 | bulk_import_configurations | INSERT | 接続設定情報保存 |
| 状態更新 | bulk_imports | UPDATE | statusカラム更新 |
| 状態更新 | bulk_import_entities | UPDATE | statusカラム更新 |

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

#### bulk_imports

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | user_id | current_user.id | インポート実行ユーザー |
| INSERT | source_type | 0 (gitlab) | GitLabからのインポート |
| INSERT | status | 0 (created) | 初期状態 |
| INSERT | source_version | API取得値 | ソースGitLabのバージョン |
| UPDATE | status | 1/2/3/-1/-2 | started/finished/timeout/failed/canceled |
| UPDATE | has_failures | true/false | エンティティに失敗があるか |

#### bulk_import_entities

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | source_full_path | ユーザー指定値 | ソースグループのパス |
| INSERT | destination_slug | ユーザー指定値 | インポート先スラグ |
| INSERT | destination_namespace | ユーザー指定値 | インポート先名前空間 |
| INSERT | source_type | 0 (group_entity) | グループインポート |
| INSERT | migrate_projects | ユーザー指定値 | プロジェクト移行フラグ |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|--------------|---------|
| MSG-301-001 | エラー | Specified URL cannot be used: "%{reason}" | URLがブロックされている場合 |
| MSG-301-002 | エラー | Unable to connect to server: %{error} | 接続エラー発生時 |
| MSG-301-003 | 警告 | Rate limit exceeded | リクエスト制限超過時 |

## 例外処理

| 例外状況 | 処理内容 |
|---------|---------|
| URLブロック | セッションデータをクリアし、新規グループ作成画面へリダイレクト |
| 接続エラー | エラーメッセージを表示し、新規グループ作成画面へリダイレクト |
| レート制限 | 429ステータスを返却 |
| 権限不足 | 404エラーを返却 |
| Bulk Import無効 | 404エラーを返却 |

## 備考

- Bulk Import機能は`Gitlab::CurrentSettings.bulk_import_enabled?`で有効/無効が制御される
- ポーリング間隔は3秒（`POLLING_INTERVAL = 3_000`）
- ソースGitLabの最小バージョンは14.0（プロジェクト移行は14.4以上）

---

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

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

### 推奨読解順序

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

まず、BulkImport関連のデータモデルを理解することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | bulk_import.rb | `app/models/bulk_import.rb` | 状態遷移（state_machine）、ステータス定義 |
| 1-2 | entity.rb | `app/models/bulk_imports/entity.rb` | インポート対象エンティティの構造 |
| 1-3 | configuration.rb | `app/models/bulk_imports/configuration.rb` | 接続設定情報 |

**読解のコツ**: state_machineによる状態遷移に注目。created -> started -> finished/failed/timeoutの流れを理解する。

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

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | bulk_imports_controller.rb | `app/controllers/import/bulk_imports_controller.rb` | statusアクション、createアクション |

**主要処理フロー**:
1. **行28-51**: `status`アクションでJSONとHTMLの両方を処理
2. **行60-78**: `create`アクションでインポート作成
3. **行80-83**: `realtime_changes`でポーリング応答

#### Step 3: ビューを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | status.html.haml | `app/views/import/bulk_imports/status.html.haml` | Vue.jsマウントポイント、data属性 |

**主要処理フロー**:
- **行7-16**: `#import-groups-mount-element`にVue.jsアプリがマウント
- data属性でパスやオプションが渡される

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | create_service.rb | `app/services/bulk_imports/create_service.rb` | インポート作成ロジック |
| 4-2 | get_importable_data_service.rb | `app/services/bulk_imports/get_importable_data_service.rb` | ソースからのデータ取得 |

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

```
Import::BulkImportsController
    │
    ├─ #status (GET)
    │      └─ BulkImports::GetImportableDataService#execute
    │              └─ BulkImports::Clients::HTTP (ソースGitLab API呼び出し)
    │
    ├─ #create (POST)
    │      └─ BulkImports::CreateService#execute
    │              ├─ BulkImport.create
    │              ├─ BulkImports::Entity.create
    │              └─ BulkImports::Configuration.create
    │
    └─ #realtime_changes (GET)
           └─ current_user.bulk_imports (状態取得)
```

### データフロー図

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

ソースURL/Token ───▶ BulkImportsController#configure ───▶ Session保存
                                                              │
                                                              ▼
セッション情報 ───▶ BulkImportsController#status ───▶ インポート可能グループ一覧
                                                              │
                                                              ▼
グループ選択 ───▶ BulkImportsController#create ───▶ BulkImport/Entity作成
     │                                                        │
     │                                                        ▼
     │                                              非同期Worker処理開始
     │                                                        │
     ▼                                                        ▼
ポーリング ───▶ BulkImportsController#realtime_changes ───▶ 状態更新表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| bulk_imports_controller.rb | `app/controllers/import/bulk_imports_controller.rb` | コントローラー | 画面制御・API提供 |
| status.html.haml | `app/views/import/bulk_imports/status.html.haml` | テンプレート | Vue.jsマウント用HTML |
| bulk_import.rb | `app/models/bulk_import.rb` | モデル | インポートジョブ管理 |
| entity.rb | `app/models/bulk_imports/entity.rb` | モデル | インポート対象管理 |
| create_service.rb | `app/services/bulk_imports/create_service.rb` | サービス | インポート作成ロジック |
| import.rb | `config/routes/import.rb` | ルーティング | URL定義 |
