# 帳票設計書 10-CodeQuality MR Diff Report

## 概要

本ドキュメントは、GitLabのマージリクエストにおけるコード品質差分レポートを生成する機能の帳票設計書である。

### 本帳票の処理概要

本帳票は、CIパイプラインで生成されたコード品質レポートをマージリクエストの変更ファイルに対してフィルタリングし、変更に関連する品質問題のみを抽出して表示する。これにより、レビュアーは変更箇所に関連するコード品質の問題に集中できる。

**業務上の目的・背景**：コードレビュープロセスにおいて、変更されたコードに関連する品質問題を特定することは効率的なレビューに不可欠である。この帳票により、コード品質ツール（CodeClimate等）で検出された問題のうち、マージリクエストの変更ファイルに関連するもののみを表示し、既存のコード問題と新規の問題を区別できる。

**帳票の利用シーン**：マージリクエストのレビュー時にコード品質の変化を確認する際、CI/CDパイプラインでの品質ゲートとして使用する際、コード品質の改善/劣化を追跡する際などに利用される。

**主要な出力内容**：
1. 変更ファイルに関連するコード品質問題一覧
2. 問題の詳細（説明、行番号、ファイルパス）
3. 問題の重大度

**帳票の出力タイミング**：マージリクエストのCodeQualityウィジェットが表示される際にリアクティブキャッシング経由でデータが取得される。

**帳票の利用者**：開発者、コードレビュアー、品質管理担当者

## 帳票種別

品質レポート（JSON出力）

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| - | Merge Request Widget | `/:namespace/:project/-/merge_requests/:id` | 自動表示（CodeQualityウィジェット） |
| - | Merge Request Diffs | `/:namespace/:project/-/merge_requests/:id/diffs` | 行別CodeQuality表示 |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | JSON |
| 用紙サイズ | - |
| 向き | - |
| ファイル名 | - |
| 出力方法 | リアクティブキャッシング |
| 文字コード | UTF-8 |

### レスポンス構造

```json
{
  "status": "parsed",
  "key": [base_pipeline_id, base_updated_at, head_pipeline_id, head_updated_at],
  "data": {
    "files": {
      "path/to/file.rb": [
        {
          "description": "問題の説明",
          "severity": "minor",
          "line": 10
        }
      ]
    }
  }
}
```

| フィールド | 説明 |
|-----------|------|
| status | 処理状態（parsed/error） |
| key | キャッシュキー（パイプラインID+更新日時） |
| data | ファイル別コード品質問題 |

## 帳票レイアウト

### レイアウト概要

JSONレスポンスはstatus、key、dataの3つの主要フィールドで構成される。dataはファイルパスをキーとした品質問題の配列。

```
{
  "status": "処理状態",
  "key": [キャッシュキー配列],
  "data": {
    "files": {
      "ファイルパス": [
        {
          "description": "問題の説明",
          "severity": "重大度",
          "line": 行番号
        }
      ]
    }
  }
}
```

### データ項目

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | status | 処理状態 | サービス処理結果 | 文字列（parsed/error） |
| 2 | key | キャッシュキー | パイプライン情報 | 配列 |
| 3 | data.files | ファイル別問題一覧 | code_quality_mr_diffアーティファクト | オブジェクト |
| 4 | description | 問題の説明 | CodeQualityレポート | 文字列 |
| 5 | severity | 重大度 | CodeQualityレポート | 文字列 |
| 6 | line | 行番号 | CodeQualityレポート | 数値 |

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| base_pipeline | ベースパイプライン | No（比較用、未使用） |
| head_pipeline | ヘッドパイプライン | Yes |
| merge_request | 対象マージリクエスト | Yes |

### フィルタリング

| 優先度 | 項目 | 説明 |
|-------|------|-----|
| 1 | MR変更ファイル | マージリクエストの変更ファイルのみを対象 |

### 改ページ条件

JSON形式のため該当なし

## データベース参照仕様

### 参照テーブル一覧

| テーブル名 | 用途 | 結合条件 |
|-----------|------|---------|
| ci_pipelines | パイプライン情報 | 主テーブル |
| ci_pipeline_artifacts | CodeQualityアーティファクト | ci_pipelines.id = ci_pipeline_artifacts.pipeline_id |
| merge_requests | マージリクエスト情報 | params[:id] |

### テーブル別参照項目詳細

#### ci_pipeline_artifacts

| 参照項目（カラム名） | 帳票項目との対応 | 取得条件 | 備考 |
|-------------------|----------------|---------|------|
| file_type | - | :code_quality_mr_diff | ファイル種別 |
| file | CodeQuality JSON | - | CarrierWaveファイル |

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| key | [base_pipeline.id, base_pipeline.updated_at, head_pipeline.id, head_pipeline.updated_at] | - | キャッシュ有効性確認用 |
| filtered_data | for_files(merge_request) | - | MR変更ファイルでフィルタ |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[MRウィジェット表示] --> B[GenerateCodequalityMrDiffReportService.execute]
    B --> C[MergeRequest.find_by_id]
    C --> D[head_pipeline.pipeline_artifacts取得]
    D --> E[find_by_file_type :code_quality_mr_diff]
    E --> F[present.for_files merge_request]
    F --> G{正常完了?}
    G -->|Yes| H[status: parsed返却]
    G -->|No| I[StandardError発生]
    I --> J[Gitlab::ErrorTracking.track_exception]
    J --> K[status: error返却]
    H --> L[keyを付与して返却]
    K --> L
    L --> M[latest?でキャッシュ有効性確認]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| 取得エラー | StandardError発生 | "An error occurred while fetching codequality mr diff reports." | エラーログ確認 |
| MR未検出 | MergeRequest.find_by_idがnil | - | エラーとして処理 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | 変更ファイル数と問題数に依存 |
| 目標出力時間 | リアクティブキャッシング使用 |
| 同時出力数上限 | リクエスト単位 |

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

- パイプラインへのアクセス権限が必要
- マージリクエストへのアクセス権限が必要
- コード品質レポートにはソースコードの構造情報が含まれる
- エラー時はGitlab::ErrorTrackingを使用してログに記録

## 備考

- CompareReportsBaseServiceを継承しているが、実際にはレポート比較は行わない
- base_pipelineは未使用（TODOコメントに記載あり）
- feature_categoryはcode_quality
- issue: https://gitlab.com/gitlab-org/gitlab/issues/34224 で設計の見直しが予定されている
- pipeline_artifactsのpresentメソッドでPresenterを取得

---

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

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

### 推奨読解順序

#### Step 1: サービスクラスを理解する

レポート生成サービスの実装を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | generate_codequality_mr_diff_report_service.rb | `app/services/ci/generate_codequality_mr_diff_report_service.rb` | executeメソッド（10-24行目） |

**読解のコツ**: TODOコメントに設計意図が記載されている。CompareReportsBaseServiceを継承しているが比較機能は使用していない。

#### Step 2: マージリクエストの取得を理解する

MRの特定とフィルタリングを確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | generate_codequality_mr_diff_report_service.rb | `app/services/ci/generate_codequality_mr_diff_report_service.rb` | MergeRequest.find_by_id（11行目） |
| 2-2 | generate_codequality_mr_diff_report_service.rb | `app/services/ci/generate_codequality_mr_diff_report_service.rb` | for_files(merge_request)（15行目） |

**主要処理フロー**:
1. **11行目**: params[:id]からマージリクエストを取得
2. **14-15行目**: pipeline_artifactsから:code_quality_mr_diffを取得し、MR変更ファイルでフィルタ

#### Step 3: エラーハンドリングを理解する

エラー発生時の処理を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | generate_codequality_mr_diff_report_service.rb | `app/services/ci/generate_codequality_mr_diff_report_service.rb` | rescueブロック（17-24行目） |

**主要処理フロー**:
- **17行目**: StandardErrorをキャッチ
- **18行目**: Gitlab::ErrorTracking.track_exceptionでログ記録
- **19-24行目**: エラーレスポンス返却

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

```
Ci::GenerateCodequalityMrDiffReportService
    │
    ├─ CompareReportsBaseService (継承)
    │      │
    │      ├─ key(base_pipeline, head_pipeline)
    │      │      └─ [base.id, base.updated_at, head.id, head.updated_at]
    │      │
    │      └─ latest?(base_pipeline, head_pipeline, data)
    │             └─ data[:key] == key(...)
    │
    ├─ execute(base_pipeline, head_pipeline)
    │      │
    │      ├─ MergeRequest.find_by_id(params[:id])
    │      │
    │      ├─ head_pipeline.pipeline_artifacts
    │      │      └─ find_by_file_type(:code_quality_mr_diff)
    │      │             └─ present.for_files(merge_request)
    │      │
    │      └─ rescue StandardError
    │             └─ Gitlab::ErrorTracking.track_exception
    │
    └─ latest?(base_pipeline, head_pipeline, data)
           └─ キャッシュ有効性確認
```

### データフロー図

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

MRウィジェット ───▶ GenerateCodequalityMrDiffReportService
    │                      │
    │                      ▼
params[:id] ───▶ MergeRequest.find_by_id
    │                      │
    ▼                      ▼
head_pipeline ───▶ pipeline_artifacts
    │                      │
    │                      ▼
    │              find_by_file_type(:code_quality_mr_diff)
    │                      │
    │                      ▼
merge_request ───▶ for_files フィルタ ───▶ status: parsed
    │                                          │
    │                                          ▼
    └─────────────────────────────────▶ JSON返却
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| generate_codequality_mr_diff_report_service.rb | `app/services/ci/generate_codequality_mr_diff_report_service.rb` | ソース | レポート生成サービス |
| compare_reports_base_service.rb | `app/services/ci/compare_reports_base_service.rb` | ソース | 基底クラス |
| pipeline_artifact.rb | `app/models/ci/pipeline_artifact.rb` | ソース | アーティファクトモデル |
| codequality_mr_diff_presenter.rb | `app/presenters/ci/codequality_mr_diff_presenter.rb` | ソース | プレゼンター |
