# 機能設計書 109-グループエクスポート

## 概要

本ドキュメントは、GitLabのグループエクスポート機能についての機能設計書である。

### 本機能の処理概要

グループエクスポートは、GitLabグループをtar.gzアーカイブとしてエクスポートする機能である。エクスポートファイルにはグループのメタデータ、メンバーシップ、ラベル、マイルストーン、ボード等のグループレベル設定が含まれる。サブグループも含めて階層構造を保持した状態でエクスポートされる。

**業務上の目的・背景**：グループ設定のバックアップ、他のGitLabインスタンスへの移行、グループ構造のアーカイブ保存などのユースケースに対応する。グループ階層を維持したまま移行を可能にする。

**機能の利用シーン**：
- 別のGitLabインスタンスへのグループ移行
- グループ設定のバックアップ作成
- 組織再編時のグループアーカイブ
- グループテンプレートの作成

**主要な処理内容**：
1. エクスポート権限の確認（admin_group）
2. 既存エクスポートファイルの削除
3. バージョン情報の保存
4. グループツリーのシリアライズ（サブグループ含む）
5. tar.gzアーカイブの作成
6. 監査ログの記録
7. 完了/失敗通知

**関連システム・外部連携**：
- Sidekiq（非同期エクスポート: GroupExportWorker）
- オブジェクトストレージ（エクスポートファイル保存）
- 通知サービス（完了/失敗通知）
- 監査ログ（エクスポート記録）

**権限による制御**：
- グループへの`admin_group`権限が必要

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | グループ設定 > 一般 | 主画面 | グループエクスポートの開始 |

## 機能種別

データエクスポート / アーカイブ作成 / バックグラウンド処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| group_id | Integer | Yes | グループID | 有効なグループID |
| params | Hash | No | エクスポートオプション | - |
| exported_by_admin | Boolean | No | 管理者エクスポートフラグ | - |

### 入力データソース

- グループ設定画面
- API呼び出し

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| export_file | File | tar.gzアーカイブ |

### 出力先

- オブジェクトストレージ（ImportExportUpload）
- ダウンロード（ユーザー）

## 処理フロー

### 処理シーケンス

```
1. 権限チェック
   └─ admin_group権限を確認
2. 既存エクスポート削除
   └─ 同ユーザーの既存エクスポートを削除
3. エクスポート開始
   └─ ログ出力
4. 各コンポーネントのエクスポート
   └─ version_saver, tree_exporter
5. アーカイブ作成
   └─ file_saverでtar.gzを生成
6. 監査ログ記録
   └─ group_export_createdイベント
7. 完了通知
   └─ 成功/失敗をメール通知
8. クリーンアップ
   └─ 一時ファイルを削除
```

### フローチャート

```mermaid
flowchart TD
    A[エクスポート開始] --> B{admin_group権限?}
    B -->|No| C[権限エラー]
    B -->|Yes| D{既存エクスポート?}
    D -->|Yes| E[既存エクスポート削除]
    D -->|No| F[Savers実行]
    E --> F
    F --> G{全Saver成功?}
    G -->|No| H[エラー通知]
    G -->|Yes| I[アーカイブ作成]
    I --> J{アーカイブ成功?}
    J -->|No| H
    J -->|Yes| K[監査ログ記録]
    K --> L[成功通知]
    L --> M[一時ファイル削除]
    H --> M
    C --> M
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-109-01 | 権限要件 | admin_group権限が必要 | 全エクスポート |
| BR-109-02 | 既存エクスポート削除 | 同ユーザーの既存エクスポートは削除される | エクスポート開始時 |
| BR-109-03 | サブグループ含有 | サブグループも階層順でエクスポート | 全エクスポート |
| BR-109-04 | サイレント管理者エクスポート | 管理者エクスポートで設定有効時は監査ログをスキップ | 管理者エクスポート |
| BR-109-05 | 一時ファイルクリーンアップ | 処理終了時に一時ファイルを削除 | 全エクスポート |

### 計算ロジック

エクスポート対象グループ:
- 対象グループとその全サブグループ（depth順）
- ObjectHierarchyで階層取得

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| メタデータ取得 | groups, members, labels等 | SELECT | グループ関連データ取得 |
| エクスポート削除 | import_export_uploads | UPDATE | 既存エクスポートファイル削除 |
| エクスポート保存 | import_export_uploads | INSERT/UPDATE | エクスポートファイル情報保存 |
| 監査ログ | audit_events | INSERT | エクスポート実行記録 |

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

#### import_export_uploads テーブル

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | export_file | NULL（削除時） | 既存エクスポート削除 |
| INSERT/UPDATE | export_file | エクスポートファイルパス | - |
| INSERT/UPDATE | group_id | グループID | - |
| INSERT/UPDATE | user_id | 実行ユーザーID | - |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | PermissionError | 権限不足 | 権限を確認 |
| - | ExportError | エクスポート失敗 | エラー内容を確認 |
| - | 通知 | 各種エラー | メール通知で確認 |

### リトライ仕様

- エクスポート失敗時は手動で再実行が必要

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

- 読み取り専用操作が主体
- エクスポート完了時にファイル情報をDB保存

## パフォーマンス要件

- 大規模グループ（多数のサブグループ）はバックグラウンドで実行
- サブグループ数に比例して処理時間増加

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

- エクスポートファイルにはグループ設定が含まれる
- アクセス権限を持つユーザーのみダウンロード可能
- 監査ログへの記録（サイレントモード除く）
- 管理者エクスポートはsilent_admin_exports_enabled設定で監査スキップ可能

## 備考

- 非同期エクスポートはGroupExportWorkerで処理
- NdjsonWriter形式でJSON出力
- EE機能でサブグループやプロジェクトの追加エクスポート対応

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | export_service.rb | `app/services/groups/import_export/export_service.rb` | エクスポートサービスの全体構造 |

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | export_service.rb | `app/services/groups/import_export/export_service.rb` | メインエクスポート処理 |

**主要処理フロー**:
1. **6-13行目**: 初期化処理（グループ、ユーザー、パラメータ）
2. **15-21行目**: `async_execute`で非同期エクスポート（GroupExportWorker）
3. **23-31行目**: `execute`メソッドで同期エクスポート
4. **38-44行目**: `validate_user_permissions`で権限チェック
5. **53-63行目**: `save!`で保存処理（savers実行 + file_saver）
6. **65-73行目**: `save_exporters`で各セーバー実行
7. **75-77行目**: `savers`でversion_saverとtree_exporter
8. **114-126行目**: `audit_export`で監査ログ記録
9. **128-132行目**: `notify_success`で成功通知

#### Step 3: ツリー保存処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | tree_saver.rb | `lib/gitlab/import_export/group/tree_saver.rb` | グループツリーのシリアライズ |

**主要処理フロー**:
1. **17-33行目**: `save`メソッドでグループをシリアライズ
2. **37-42行目**: `groups`でサブグループも含めて階層取得（depth順）
3. **44-52行目**: `serialize`で各グループをJSON化

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

```
Groups::ImportExport::ExportService
    │
    ├─ async_execute
    │      └─ GroupExportWorker.perform_async
    │
    └─ execute
           │
           ├─ validate_user_permissions
           │      └─ can?(:admin_group, group)
           │
           ├─ remove_existing_export!
           │      └─ import_export_upload.remove_export_file!
           │
           └─ save!
                  │
                  ├─ save_exporters
                  │      ├─ VersionSaver.save
                  │      └─ Group::TreeSaver.save
                  │             │
                  │             ├─ groups (ObjectHierarchy)
                  │             ├─ serialize (StreamingSerializer)
                  │             └─ NdjsonWriter
                  │
                  ├─ file_saver.save
                  │      └─ Saver.save
                  │
                  ├─ audit_export
                  │      └─ Gitlab::Audit::Auditor.audit
                  │
                  └─ notify_success
                         └─ NotificationService.group_was_exported
```

### データフロー図

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

グループ ─────────────────▶ ExportService ───────────────▶ tar.gzアーカイブ
                              │
                              ├─ VersionSaver
                              │      └─ VERSION.json
                              │
                              ├─ TreeSaver
                              │      │
                              │      ├─ サブグループ取得
                              │      │      └─ ObjectHierarchy
                              │      │
                              │      └─ シリアライズ
                              │             └─ NDJSON形式
                              │
                              └─ Saver
                                     └─ tar.gz作成
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| export_service.rb | `app/services/groups/import_export/export_service.rb` | ソース | メインエクスポートサービス |
| tree_saver.rb | `lib/gitlab/import_export/group/tree_saver.rb` | ソース | グループツリー保存 |
| version_saver.rb | `lib/gitlab/import_export/version_saver.rb` | ソース | バージョン情報保存 |
| saver.rb | `lib/gitlab/import_export/saver.rb` | ソース | アーカイブ作成 |
| ndjson_writer.rb | `lib/gitlab/import_export/json/ndjson_writer.rb` | ソース | NDJSON形式出力 |
| group_export_worker.rb | `app/workers/group_export_worker.rb` | ソース | 非同期エクスポート |
