# 画面設計書 294-Manifestインポート

## 概要

本ドキュメントは、GitLabにおけるManifestファイルを使用したリポジトリ一括インポート開始画面の設計を記載したものである。

### 本画面の処理概要

Android Source Project（repo）形式のManifestファイルをアップロードし、複数のGitリポジトリを一括でインポートするための開始画面である。Manifestファイルに記載された複数のリポジトリ情報を解析し、インポート対象として登録する。

**業務上の目的・背景**：Android Open Source Project（AOSP）やその他の大規模プロジェクトでは、多数のGitリポジトリを管理するために`repo`ツールとManifestファイルを使用する。このManifestファイルをGitLabにインポートすることで、AOSPベースのプロジェクトや類似の大規模リポジトリ構成をGitLabに移行できる。

**画面へのアクセス方法**：
1. サイドバーまたはヘッダーから「プロジェクト新規作成」を選択
2. 「Import project」タブを選択
3. 「Manifest file」を選択して本画面にアクセス

**主要な操作・処理内容**：
1. インポート先グループの選択
2. ManifestファイルのXMLファイルをアップロード
3. 「List available repositories」ボタンでManifestを解析
4. 成功時、Manifestインポート状態画面へリダイレクト

**画面遷移**：
- 遷移元：プロジェクト新規作成画面（インポート選択）
- 遷移先：Manifestインポート状態画面（No.295）

**権限による表示制御**：
- プロジェクト作成権限を持つユーザーのみがアクセス可能
- インポート先グループに対するインポート権限が必要

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 110 | バルクインポート | 主機能 | Manifestファイルによる一括インポート開始処理 |

## 画面種別

登録（ファイルアップロード）

## URL/ルーティング

```
GET /import/manifest/new
POST /import/manifest/upload
```

ルーティング定義: `config/routes/import.rb`
```ruby
resource :manifest, only: [:create, :new], controller: :manifest do
  get :status
  get :realtime_changes
  post :upload
end
```

## 入出力項目

| 項目名 | 項目ID | 型 | 必須 | 説明 |
|--------|--------|-----|------|------|
| グループ | group_id | 整数 | 必須 | インポート先のグループID |
| Manifestファイル | manifest | ファイル | 必須 | XMLフォーマットのManifestファイル |

## 表示項目

| 項目名 | 説明 |
|--------|------|
| ページタイトル | 「Manifest file import」 |
| グループ選択 | インポート先グループのドロップダウン |
| ファイルアップロード | Manifestファイル選択フィールド |
| 説明リンク | Manifestインポートのヘルプページへのリンク |

## イベント仕様

### 1-アップロードボタン押下（従来UI）

「List available repositories」ボタンを押下すると以下の処理が実行される：

```ruby
# app/controllers/import/manifest_controller.rb (行22-60)
def upload
  group = Group.find(params[:group_id])

  unless can?(current_user, :import_projects, group)
    @errors = [s_("ManifestImport|You don't have enough permissions to import projects in the selected group")]
  end

  unless @errors
    manifest = Gitlab::ManifestImport::Manifest.new(params[:manifest].tempfile)

    if manifest.valid?
      manifest_import_metadata.save(manifest.projects, group.id)

      respond_to do |format|
        format.json do
          render json: { success: true }
        end
        format.html do
          redirect_to status_import_manifest_path
        end
      end

      return
    end

    @errors = manifest.errors
  end
  # エラー処理...
end
```

### 2-Vueフォーム送信（Feature Flag有効時）

Feature Flag `new_project_creation_form` が有効な場合、Vue.jsコンポーネントが使用される：

1. グループ選択コンポーネントでグループを選択
2. ドラッグ&ドロップまたはクリックでファイルをアップロード
3. axios経由でPOSTリクエストを送信
4. 成功時、状態画面へリダイレクト

```javascript
// app/assets/javascripts/import/manifest/import_manifest_file_app.vue (行81-98)
async onSubmit() {
  if (!this.uploadError) {
    if (this.file) {
      const formData = new FormData();
      formData.append('manifest', this.file);
      formData.append('group_id', this.groupId);

      try {
        await axios.post(this.formPath, formData);
        visitUrl(this.statusImportManifestPath);
      } catch (error) {
        // エラー処理
      }
    } else {
      this.uploadError = s__('ManifestImport|Please upload a manifest file.');
    }
  }
}
```

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| upload | - | - | セッション/メタデータストアに保存。DBへの直接書き込みは発生しない |

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

本画面ではデータベースへの直接更新は発生しない。`Gitlab::ManifestImport::Metadata`を通じてセッションまたはRedisにManifest情報を保存する。

保存されるデータ：
- Manifestから解析されたプロジェクト一覧（リポジトリURL、パス等）
- インポート先グループID

## メッセージ仕様

| メッセージID | メッセージ種別 | メッセージ内容 | 表示条件 |
|-------------|---------------|---------------|---------|
| MSG001 | エラー | You don't have enough permissions to import projects in the selected group | グループへのインポート権限がない場合 |
| MSG002 | エラー | Import manifest files cannot exceed {size} MB | ファイルサイズ超過時（1MB制限） |
| MSG003 | エラー | {manifest.errors} | Manifestファイルの解析エラー時 |
| MSG004 | バリデーション | Please upload a manifest file. | ファイル未選択時（Vueコンポーネント） |
| MSG005 | バリデーション | Unable to upload the file. Please upload a valid XML file. | 無効なファイル形式時（Vueコンポーネント） |

## 例外処理

| 例外パターン | 処理内容 |
|-------------|---------|
| インポート機能無効 | 404エラーページを表示 |
| ファイルサイズ超過 | エラーメッセージを表示して再入力を促す |
| XML解析エラー | Manifestのエラー内容を表示して再入力を促す |
| 権限不足 | エラーメッセージを表示 |

## 備考

- Manifestファイルの最大サイズは1MB
- 許可されるファイル形式はXMLのみ
- Android repoツールのManifestフォーマットに対応
- Feature Flag `new_project_creation_form` によりUIが切り替わる

---

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

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

### 推奨読解順序

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

Manifestファイルの構造とメタデータ保存の仕組みを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | manifest_controller.rb | `app/controllers/import/manifest_controller.rb` | manifest_import_metadata（行115-117） |
| 1-2 | Manifest関連クラス | `lib/gitlab/manifest_import/` | Manifestの解析ロジック |

**読解のコツ**: ManifestはXML形式で複数のリポジトリ情報を含む。Metadataクラスでセッションへの保存を管理。

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

newアクションとuploadアクションを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | manifest_controller.rb | `app/controllers/import/manifest_controller.rb` | new（行13）、upload（行22-60） |
| 2-2 | import.rb | `config/routes/import.rb` | Manifest関連ルーティング（行86-90） |

**主要処理フロー**:
1. **行13**: `new`アクション - 初期表示
2. **行22-60**: `upload`アクション - Manifestファイル解析・保存

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

画面表示の実装を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | new.html.haml | `app/views/import/manifest/new.html.haml` | Feature Flagによる分岐 |
| 3-2 | _form.html.haml | `app/views/import/manifest/_form.html.haml` | 従来フォーム |
| 3-3 | import_manifest_file_app.vue | `app/assets/javascripts/import/manifest/import_manifest_file_app.vue` | Vueコンポーネント |

**主要処理フロー**:
- **new.html.haml行6-12**: Feature Flag有効時はVueコンポーネントをマウント
- **行13-18**: Feature Flag無効時は従来のHAMLフォームを表示

#### Step 4: バリデーション処理を理解する

ファイルサイズとManifest形式の検証を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | manifest_controller.rb | `app/controllers/import/manifest_controller.rb` | check_file_size（行131-147）、MAX_MANIFEST_SIZE_IN_MB（行6） |

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

```
GET /import/manifest/new
    │
    └─ Import::ManifestController#new
           └─ app/views/import/manifest/new.html.haml
                  │
                  ├─ [Feature Flag ON]
                  │      └─ import_manifest_file_app.vue
                  │
                  └─ [Feature Flag OFF]
                         └─ _form.html.haml

POST /import/manifest/upload
    │
    └─ Import::ManifestController#upload
           │
           ├─ check_file_size (before_action)
           │
           ├─ Group.find(params[:group_id])
           │
           ├─ can?(current_user, :import_projects, group)
           │
           ├─ Gitlab::ManifestImport::Manifest.new
           │      └─ manifest.valid? / manifest.projects
           │
           └─ manifest_import_metadata.save
                  └─ redirect_to status_import_manifest_path
```

### データフロー図

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

Manifest XML      ───▶  Gitlab::ManifestImport::        ───▶  projects配列
ファイル                 Manifest#valid?                       (パース結果)
                                                              │
                                                              ▼
グループID        ───▶  ManifestImport::Metadata       ───▶  セッション/Redis
+ パース結果             #save                                 保存
                                                              │
                                                              ▼
                                                         状態画面へリダイレクト
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| manifest_controller.rb | `app/controllers/import/manifest_controller.rb` | コントローラー | リクエスト処理 |
| new.html.haml | `app/views/import/manifest/new.html.haml` | テンプレート | 初期画面表示 |
| _form.html.haml | `app/views/import/manifest/_form.html.haml` | パーシャル | 従来フォーム |
| import_manifest_file_app.vue | `app/assets/javascripts/import/manifest/import_manifest_file_app.vue` | Vueコンポーネント | 新UIフォーム |
| import.rb | `config/routes/import.rb` | ルーティング | URLルーティング定義 |
| manifest.rb | `lib/gitlab/manifest_import/manifest.rb` | ライブラリ | Manifest解析 |
| metadata.rb | `lib/gitlab/manifest_import/metadata.rb` | ライブラリ | メタデータ保存 |
