# 画面設計書 70-ジョブ詳細

## 概要

本ドキュメントは、GitLabプロジェクトのジョブ詳細画面の設計仕様を定義するものである。

### 本画面の処理概要

本画面は、特定のCI/CDジョブの詳細情報とログを表示する画面である。ジョブの実行ログをリアルタイムで確認し、アーティファクトのダウンロードや各種操作（キャンセル、リトライ、プレイ）を行える。

**業務上の目的・背景**：CI/CDジョブの実行結果を詳細に確認し、問題が発生した場合のデバッグや、成果物の取得を行うための画面である。リアルタイムログ表示により、実行中のジョブの進捗を監視できる。

**画面へのアクセス方法**：
1. ジョブ一覧画面からジョブ行をクリック
2. パイプライン詳細画面からジョブをクリック
3. URLに直接`/-/jobs/:id`を入力

**主要な操作・処理内容**：
1. ジョブログのリアルタイム表示
2. ジョブのキャンセル
3. ジョブのリトライ
4. 手動ジョブのプレイ（変数指定可能）
5. スケジュール解除
6. アーティファクトのダウンロード
7. ジョブログの消去
8. ターミナルアクセス（設定時）

**画面遷移**：
- 遷移元：ジョブ一覧画面、パイプライン詳細画面
- 遷移先：パイプライン詳細画面、アーティファクトブラウザ、ターミナル

**権限による表示制御**：
- 閲覧権限（Guest以上、設定による）：ジョブ詳細とログの表示
- ログ閲覧権限：ジョブログの表示
- 更新権限（Developer以上）：キャンセル、リトライ、プレイ
- 消去権限：ジョブログとアーティファクトの消去
- ターミナル権限：ターミナルアクセス

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 47 | パイプライン実行 | 主機能 | ジョブの詳細表示と操作 |

## 画面種別

詳細

## URL/ルーティング

| メソッド | URL | アクション | 説明 |
|----------|-----|-----------|------|
| GET | `/:namespace_id/:project_id/-/jobs/:id` | show | ジョブ詳細画面表示 |
| GET | `/:namespace_id/:project_id/-/jobs/:id.json` | show | ジョブ詳細（JSON） |
| GET | `/:namespace_id/:project_id/-/jobs/:id/trace.json` | trace | ログ取得（JSON） |
| GET | `/:namespace_id/:project_id/-/jobs/:id/raw` | raw | 生ログダウンロード |
| GET | `/:namespace_id/:project_id/-/jobs/:id/viewer` | viewer | ログビューア |
| POST | `/:namespace_id/:project_id/-/jobs/:id/cancel` | cancel | ジョブキャンセル |
| POST | `/:namespace_id/:project_id/-/jobs/:id/retry` | retry | ジョブリトライ |
| POST | `/:namespace_id/:project_id/-/jobs/:id/play` | play | 手動ジョブ実行 |
| POST | `/:namespace_id/:project_id/-/jobs/:id/unschedule` | unschedule | スケジュール解除 |
| POST | `/:namespace_id/:project_id/-/jobs/:id/erase` | erase | ログ・アーティファクト消去 |
| GET | `/:namespace_id/:project_id/-/jobs/:id/terminal` | terminal | ターミナル画面 |
| GET | `/:namespace_id/:project_id/-/jobs/:id/test_report_summary` | test_report_summary | テストレポートサマリー |

## 入出力項目

### 入力パラメータ

| 項目名 | データ型 | 必須 | 説明 |
|--------|---------|------|------|
| id | integer | ○ | ジョブID |
| state | string | - | ログ取得状態（trace用） |
| force | boolean | - | 強制キャンセルフラグ |
| job_variables_attributes | array | - | プレイ時の変数 |

### プレイ時変数

| 項目名 | データ型 | 必須 | 説明 |
|--------|---------|------|------|
| key | string | - | 変数キー |
| secret_value | string | - | 変数値 |

## 表示項目

| 項目名 | データ型 | 説明 |
|--------|---------|------|
| ジョブID | integer | ジョブのID |
| ジョブ名 | string | ジョブの名前 |
| 状態 | string | running/pending/success/failed等 |
| 実行ログ | text | ジョブの実行ログ（リアルタイム更新） |
| ステージ | string | 所属ステージ名 |
| パイプライン | object | 所属パイプライン情報 |
| コミット情報 | object | 関連コミット情報 |
| 実行ユーザー | object | ジョブ実行者 |
| 実行時間 | duration | ジョブの実行時間 |
| 作成日時 | datetime | ジョブ作成日時 |
| 開始日時 | datetime | ジョブ開始日時 |
| 完了日時 | datetime | ジョブ完了日時 |
| ランナー | object | 実行ランナー情報 |
| タグ | array | ジョブのタグ |
| カバレッジ | float | コードカバレッジ |
| アーティファクト | array | 生成されたアーティファクト |
| テストレポート | object | テスト結果サマリー |

## イベント仕様

### 1-ログストリーミング

ジョブ実行中は自動的にログをポーリング（10秒間隔）して表示を更新する。trace.being_watched!で監視状態を通知。

### 2-ジョブキャンセル

「Cancel」ボタンをクリックすると、BuildCancelServiceが呼び出され、実行中のジョブがキャンセルされる。

### 3-ジョブリトライ

「Retry」ボタンをクリックすると、RetryJobServiceが呼び出され、ジョブが再実行される。

### 4-手動ジョブプレイ

「Play」ボタンをクリックすると、手動ジョブが実行される。変数を指定可能。

### 5-スケジュール解除

「Unschedule」ボタンをクリックすると、スケジュールされたジョブが解除される。

### 6-アーティファクトダウンロード

「Download artifacts」ボタンをクリックすると、ジョブのアーティファクトがダウンロードされる。

### 7-ログ消去

「Erase」ボタンをクリックすると、ジョブログとアーティファクトが削除される。

### 8-生ログダウンロード

「raw」リンクをクリックすると、ログがテキストファイルとしてダウンロードされる。

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 画面表示 | ci_builds | SELECT | ジョブ情報取得 |
| 画面表示 | ci_job_artifacts | SELECT | アーティファクト情報取得 |
| キャンセル | ci_builds | UPDATE | ステータス更新 |
| リトライ | ci_builds | INSERT | 新規ジョブレコード作成 |
| プレイ | ci_builds | UPDATE | ステータス更新 |
| スケジュール解除 | ci_builds | UPDATE | ステータス更新 |
| 消去 | ci_builds | UPDATE | ログ消去 |
| 消去 | ci_job_artifacts | DELETE | アーティファクト削除 |

## メッセージ仕様

| 種別 | メッセージ | 表示条件 |
|------|----------|---------|
| 成功 | Job has been successfully erased! | 消去成功時 |
| エラー | 422 Unprocessable Entity | リトライ失敗時 |
| 情報 | This job is stuck | ランナー不足時 |
| 情報 | This job is in a delayed state | 遅延実行時 |

## 例外処理

| 例外状況 | 処理内容 |
|---------|---------|
| ジョブが見つからない | 404エラーページを表示 |
| 閲覧権限がない | 403エラーページを表示 |
| Ci::Bridgeの場合 | パイプライン詳細にリダイレクト |
| リトライ権限がない | アクセス拒否 |
| プレイ権限がない | アクセス拒否 |
| プレイ不可状態 | 422エラー |

## 備考

- ポーリング間隔は10秒（10_000ms）
- Vue.jsコンポーネントで実装（#js-job-page）
- Ci::Bridgeの場合は下流パイプラインにリダイレクト
- ターミナル機能はWebSocket使用
- ログはBuildTraceSerializerでシリアライズ
- アーティファクトはWorkhorse経由でダウンロード

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | jobs_controller.rb | `app/controllers/projects/jobs_controller.rb` | showアクションと各種アクション |

**主要処理フロー**:
1. **行34-63**: `show`アクション - Ci::Bridge判定、HTML/JSON分岐
2. **行65-86**: `trace`アクション - ログストリーミング
3. **行88-104**: `retry`アクション - リトライ処理
4. **行106-117**: `play`アクション - 手動実行
5. **行119-130**: `cancel`アクション - キャンセル処理
6. **行132-144**: `unschedule`アクション - スケジュール解除
7. **行146-154**: `erase`アクション - ログ消去

#### Step 2: ビュー層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | show.html.haml | `app/views/projects/jobs/show.html.haml` | メインビュー（行1-10） |
| 2-2 | jobs_helper.rb | `app/helpers/ci/jobs_helper.rb` | `jobs_data`メソッド（行5-22） |

**主要処理フロー**:
- **行10**: `#js-job-page`でVueコンポーネントをマウント
- `jobs_data`メソッドで以下のデータを設定：
  - job_endpoint, log_endpoint
  - test_report_summary_url, page_path
  - runner_settings_url, pipeline_test_report_url
  - log_viewer_path, can_set_pipeline_variables

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

```
HTTP Request (GET /project/-/jobs/:id)
    │
    ├─ JobsController#show
    │      │
    │      ├─ find_job_as_processable
    │      │      └─ project.processables.find(id)
    │      │
    │      ├─ Ci::Bridge 判定
    │      │      └─ redirect_to pipeline (Bridge の場合)
    │      │
    │      └─ respond_to
    │             │
    │             ├─ format.html → render 'show'
    │             │      └─ jobs_data(@project, @build)
    │             │
    │             └─ format.json
    │                    ├─ PollingInterval (10秒)
    │                    └─ Ci::JobSerializer → BuildDetailsEntity
    │
    └─ Vue.js コンポーネント (フロントエンド)
           ├─ Job Header
           ├─ Job Log
           └─ Job Sidebar

HTTP Request (GET /project/-/jobs/:id/trace.json)
    │
    └─ JobsController#trace
           │
           ├─ @build.trace.being_watched! (running時)
           │
           └─ @build.trace.read
                  └─ BuildTraceSerializer

HTTP Request (POST /project/-/jobs/:id/retry)
    │
    └─ JobsController#retry
           │
           ├─ can?(current_user, :retry_job, @build)
           │
           └─ Ci::RetryJobService#execute
                  └─ 新規ジョブ作成

HTTP Request (POST /project/-/jobs/:id/cancel)
    │
    └─ JobsController#cancel
           │
           └─ Ci::BuildCancelService#execute
                  └─ ステータス更新
```

### データフロー図

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

Job ID ─────────────▶ JobsController#show ─────────▶ ジョブ詳細画面
                              │
                              ├─ jobs_data
                              │      ├─ job_endpoint
                              │      ├─ log_endpoint
                              │      └─ test_report_summary_url
                              │
                              └─ Ci::JobSerializer
                                     └─ BuildDetailsEntity
                                            │
                                            ▼
                              ──────────▶ Vue.js表示

trace Request ─────────▶ trace ───────────────────▶ ログデータ
                              │
                              └─ @build.trace.read
                                     └─ BuildTraceSerializer
                                            │
                                            ▼
                              ──────────▶ JSON応答

Cancel/Retry/Play ──────▶ 各アクション ───────────▶ 操作結果
                              │
                              └─ 各Service
                                     └─ DB更新
                                            │
                                            ▼
                              ──────────▶ リダイレクト
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| jobs_controller.rb | `app/controllers/projects/jobs_controller.rb` | コントローラー | リクエストハンドリング |
| show.html.haml | `app/views/projects/jobs/show.html.haml` | ビュー | メインビュー |
| jobs_helper.rb | `app/helpers/ci/jobs_helper.rb` | ヘルパー | データ準備 |
| job_serializer.rb | `app/serializers/ci/job_serializer.rb` | シリアライザー | JSON変換 |
| build_details_entity.rb | `app/serializers/build_details_entity.rb` | エンティティ | 詳細データ構造 |
| build_trace_serializer.rb | `app/serializers/build_trace_serializer.rb` | シリアライザー | ログ変換 |
| retry_job_service.rb | `app/services/ci/retry_job_service.rb` | サービス | リトライ処理 |
| build_cancel_service.rb | `app/services/ci/build_cancel_service.rb` | サービス | キャンセル処理 |
| build_erase_service.rb | `app/services/ci/build_erase_service.rb` | サービス | 消去処理 |
| project.rb | `config/routes/project.rb` | ルーティング | URL定義（行53-81） |
