# 機能設計書 105-GitHubインポート

## 概要

本ドキュメントは、GitLabのGitHubからのプロジェクトインポート機能についての機能設計書である。

### 本機能の処理概要

GitHubインポートは、GitHubからGitLabへプロジェクト（リポジトリ、イシュー、プルリクエスト、コメント等）を移行する機能である。OAuth認証またはPersonal Access Tokenを使用してGitHub APIにアクセスし、データを取得・変換・インポートする。

**業務上の目的・背景**：GitHub.comやGitHub EnterpriseからGitLabへの移行を支援する。既存のプロジェクト履歴、イシュー、プルリクエストなどの開発資産を保持したまま、シームレスな移行を実現する。

**機能の利用シーン**：
- GitHubからGitLabへの組織移行
- 個人プロジェクトのGitLabへの移行
- GitHubとGitLabの並行運用時のプロジェクト同期
- GitHub Enterpriseからの移行

**主要な処理内容**：
1. GitHub OAuth認証またはPersonal Access Token検証
2. インポート可能なリポジトリ一覧の取得
3. ターゲット名前空間の選択・作成
4. リポジトリのクローンとインポート
5. イシュー、プルリクエスト、コメントのインポート
6. ラベル、マイルストーン、コラボレーターのインポート
7. インポート進捗のリアルタイム表示

**関連システム・外部連携**：
- GitHub API（REST/GraphQL）
- GitHub OAuth
- Sidekiq（バックグラウンドインポートジョブ）
- Gitaly（リポジトリ操作）

**権限による制御**：
- ターゲット名前空間への`import_projects`権限が必要
- GitHubリポジトリへの読み取りアクセスが必要
- コラボレーターインポートには`read:org`スコープが必要

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 285 | GitHubインポート | 主画面 | GitHubからのインポート開始 |
| 286 | GitHubインポート状態 | 主画面 | GitHubインポート状態表示 |
| 287 | GitHubインポート詳細 | 主画面 | GitHubインポート詳細表示 |
| 134 | インポート設定 | 主画面 | プロジェクトインポート状態の表示 |
| 135 | インポート開始 | 主画面 | インポート開始処理 |

## 機能種別

データインポート / 外部API連携 / バックグラウンド処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| repo_id | Integer | Yes | GitHubリポジトリID | 有効なリポジトリID |
| new_name | String | No | 新しいプロジェクト名 | 英数字、ハイフン、アンダースコア |
| target_namespace | String | Yes | ターゲット名前空間パス | 有効な名前空間パス |
| optional_stages | Hash | No | オプションインポート段階 | collaborators_import等 |
| timeout_strategy | String | No | タイムアウト戦略 | pessimistic/optimistic |
| pagination_limit | Integer | No | ページネーション上限 | 正の整数 |

### 入力データソース

- GitHubインポート画面
- Personal Access Token入力
- OAuth認証フロー

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| project | Object | 作成されたプロジェクト |
| import_status | String | インポート状態 |
| import_failures | Array | インポート失敗詳細 |

### 出力先

- プロジェクト（GitLab内）
- インポート状態画面
- 失敗レポート

## 処理フロー

### 処理シーケンス

```
1. 認証
   └─ OAuth認証またはPersonal Access Token検証
2. リポジトリ一覧取得
   └─ GitHub APIからユーザーのリポジトリを取得
3. リポジトリ選択
   └─ インポートするリポジトリを選択
4. ターゲット名前空間設定
   └─ インポート先の名前空間を指定
5. プロジェクト作成
   └─ GitLabにプロジェクトを作成
6. インポートジョブキュー
   └─ Sidekiqにインポートジョブを登録
7. バックグラウンドインポート
   └─ 非同期でデータをインポート
8. 進捗更新
   └─ リアルタイムで進捗を画面に反映
```

### フローチャート

```mermaid
flowchart TD
    A[インポート開始] --> B{認証方式?}
    B -->|OAuth| C[OAuth認証フロー]
    B -->|PAT| D[Personal Access Token入力]
    C --> E{認証成功?}
    D --> E
    E -->|No| F[認証エラー表示]
    E -->|Yes| G[リポジトリ一覧取得]
    G --> H{レート制限OK?}
    H -->|No| I[レート制限エラー]
    H -->|Yes| J[リポジトリ選択]
    J --> K[ターゲット名前空間選択]
    K --> L{import_projects権限?}
    L -->|No| M[権限エラー]
    L -->|Yes| N[プロジェクト作成]
    N --> O[インポートジョブ登録]
    O --> P[バックグラウンド処理]
    P --> Q{インポート成功?}
    Q -->|Yes| R[完了通知]
    Q -->|No| S[失敗レポート]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-105-01 | repoスコープ必須 | Personal Access Tokenにはrepoスコープが必要 | PAT認証時 |
| BR-105-02 | read:orgスコープ | コラボレーターインポートにはread:orgスコープが必要 | collaborators_import有効時 |
| BR-105-03 | レート制限対応 | GitHub APIレート制限に従った処理 | 全リクエスト |
| BR-105-04 | 名前重複チェック | 同名プロジェクトが存在する場合は作成不可 | プロジェクト作成時 |

### 計算ロジック

インポート進捗:
- 各インポート段階（リポジトリ、イシュー、PR等）ごとに進捗を計算
- 失敗したアイテムはスキップして継続

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| プロジェクト作成 | projects | INSERT | 新規プロジェクトレコード作成 |
| イシュー作成 | issues | INSERT | GitHubイシューをインポート |
| マージリクエスト作成 | merge_requests | INSERT | GitHubプルリクエストをインポート |
| ラベル作成 | labels | INSERT | GitHubラベルをインポート |
| インポート失敗記録 | import_failures | INSERT | 失敗したインポートを記録 |

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

#### projects テーブル

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | name | リポジトリ名またはnew_name | - |
| INSERT | path | URLセーフな形式に変換 | - |
| INSERT | namespace_id | target_namespaceのID | - |
| INSERT | import_type | 'github' | - |
| INSERT | import_source | GitHubリポジトリURL | - |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 401 | Unauthorized | 無効なアクセストークン | トークン再発行 |
| 403 | Forbidden | スコープ不足 | 必要なスコープを追加 |
| 404 | Not Found | リポジトリが存在しない | リポジトリを確認 |
| 429 | Too Many Requests | GitHub APIレート制限 | reset_time後にリトライ |

### リトライ仕様

- GitHub APIエラー: バックオフ付きリトライ
- レート制限: reset_time後に自動リトライ
- ネットワークエラー: 最大3回リトライ

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

- プロジェクト作成はトランザクション内で実行
- インポートデータはバッチ単位でコミット

## パフォーマンス要件

- リポジトリ一覧取得: ページネーション対応（25件/ページ）
- 大規模リポジトリのインポートはバックグラウンドで長時間実行可能
- タイムアウト戦略（pessimistic/optimistic）で調整可能

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

- アクセストークンはセッションに保存（DBに保存しない）
- OAuth state検証でCSRF防止
- ブロックされたURLへのアクセス防止

## 備考

- Giteaインポートも同じコントローラで処理（provider_name切り替え）
- Fine-grained tokensは非サポート（Classic PAT推奨）

---

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

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

### 推奨読解順序

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

インポートに関わるデータ構造を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | github_controller.rb | `app/controllers/import/github_controller.rb` | コントローラの全体構造 |

**読解のコツ**: `Import::BaseController`を継承し、プロバイダー固有のメソッドをオーバーライドしている。

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

HTTPリクエストの受付処理を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | github_controller.rb | `app/controllers/import/github_controller.rb` | 各アクションの処理 |

**主要処理フロー**:
1. **26-32行目**: `new`アクションでOAuth認証またはPAT入力へ
2. **34-43行目**: `callback`アクションでOAuthコールバック処理
3. **45-48行目**: `personal_access_token`アクションでPAT設定
4. **50-68行目**: `status`アクションでリポジトリ一覧表示
5. **72-79行目**: `create`アクションでインポート開始
6. **82-86行目**: `realtime_changes`でリアルタイム進捗

#### Step 3: インポートサービスを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | github_service.rb | `app/services/import/github_service.rb` | インポートサービス |

**主要処理フロー**:
- **11-37行目**: `execute`メソッドでインポート実行
- **39-41行目**: `rate_limited?`でレート制限チェック
- **43-51行目**: `create_project`でプロジェクト作成
- **91-106行目**: `validate_access_token`でトークン検証
- **172-179行目**: `store_import_settings`でインポート設定保存

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

```
Import::GithubController
    │
    ├─ #new
    │      └─ OAuth認証 or PAT入力画面
    │
    ├─ #callback
    │      └─ OAuth認証完了処理
    │
    ├─ #personal_access_token
    │      └─ PAT設定
    │
    ├─ #status
    │      └─ client_proxy.repos (リポジトリ一覧)
    │
    ├─ #create
    │      └─ Import::GithubService
    │             │
    │             ├─ validate_access_token
    │             ├─ create_project
    │             │      └─ Gitlab::LegacyGithubImport::ProjectCreator
    │             │
    │             └─ store_import_settings
    │
    └─ #realtime_changes
           └─ Import::GithubRealtimeRepoSerializer
```

### データフロー図

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

GitHub OAuth/PAT ───────▶ Import::GithubController ───────▶ プロジェクト
リポジトリ選択                  │
ターゲット名前空間              ├─ Import::GithubService
                               │      │
                               │      └─ ProjectCreator
                               │             │
                               │             └─ Sidekiqジョブ登録
                               │
                               └─ バックグラウンドインポート
                                      │
                                      ├─ リポジトリクローン
                                      ├─ イシューインポート
                                      ├─ PRインポート
                                      └─ ラベル/マイルストーンインポート
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| github_controller.rb | `app/controllers/import/github_controller.rb` | ソース | HTTPエンドポイント |
| github_service.rb | `app/services/import/github_service.rb` | ソース | インポートサービス |
| base_controller.rb | `app/controllers/import/base_controller.rb` | ソース | 基底コントローラ |
| github_oauth.rb | `app/controllers/concerns/import/github_oauth.rb` | ソース | OAuth処理 |
| project_creator.rb | `lib/gitlab/legacy_github_import/project_creator.rb` | ソース | プロジェクト作成 |
| proxy.rb | `lib/gitlab/github_import/clients/proxy.rb` | ソース | GitHub APIプロキシ |
