# 画面設計書 261-Runner編集

## 概要

本ドキュメントは、GitLab管理者エリアにおける「Runner編集」画面の設計を記載したものです。管理者がシステム全体のCI/CD Runnerの設定を編集し、プロジェクトへの割り当てを管理するための画面です。

### 本画面の処理概要

**業務上の目的・背景**：CI/CDパイプラインを実行するために、Runnerは不可欠なコンポーネントです。管理者は、Runnerの動作設定（説明、タグ、保護レベル、タイムアウト等）を適切に管理し、どのプロジェクトがそのRunnerを利用できるかを制御する必要があります。本画面は、個別Runnerの詳細設定変更とプロジェクト割り当ての一元管理を可能にし、インフラストラクチャリソースの効率的な運用を支援します。

**画面へのアクセス方法**：管理者エリア > Runner一覧 > 対象Runnerの編集ボタンをクリック、または `/admin/runners/:id/edit` に直接アクセスします。管理者権限が必要です。

**主要な操作・処理内容**：
1. Runnerの基本情報（説明、タグ、アクティブ状態）の編集
2. Runnerのアクセスレベル（保護/非保護）の設定
3. ジョブの最大タイムアウト時間の設定
4. プロジェクトタイプRunnerの場合、プロジェクト割り当ての管理
5. 割り当て済みプロジェクトの解除
6. 新規プロジェクトへのRunner割り当て

**画面遷移**：
- 遷移元：Runner詳細画面、Runner一覧画面
- 遷移先：Runner詳細画面（保存後）、プロジェクト詳細画面

**権限による表示制御**：管理者権限を持つユーザーのみがアクセス可能です。プロジェクト割り当てセクションは、プロジェクトタイプのRunnerの場合のみ表示されます。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 115 | ランナー管理 | 主機能 | Runnerの設定更新、プロジェクト割り当て管理 |
| 51 | Runnerレジストレーション | 補助機能 | Runner登録情報の参照 |

## 画面種別

編集

## URL/ルーティング

- URL: `/admin/runners/:id/edit`
- HTTPメソッド: GET（表示）、PATCH/PUT（更新）
- コントローラー: `Admin::RunnersController#edit`, `Admin::RunnersController#update`

## 入出力項目

### 入力項目（Runner設定）

| 項目名 | 物理名 | 型 | 必須 | 説明 |
|--------|--------|-----|------|------|
| 説明 | description | String | - | Runnerの説明文 |
| タグ | tag_list | Array | - | Runnerに設定するタグ（カンマ区切り） |
| アクティブ | active | Boolean | - | Runnerの有効/無効状態 |
| タグなしジョブ実行 | run_untagged | Boolean | - | タグが指定されていないジョブの実行可否 |
| ロック | locked | Boolean | - | 現在のプロジェクトにロックするか |
| アクセスレベル | access_level | Enum | - | not_protected(0) / ref_protected(1) |
| 最大タイムアウト | maximum_timeout_human_readable | String | - | 人間が読める形式のタイムアウト値 |

### 入力項目（プロジェクト検索）

| 項目名 | 物理名 | 型 | 必須 | 説明 |
|--------|--------|-----|------|------|
| 検索キーワード | search | String | - | プロジェクト名での検索 |

## 表示項目

### Runner情報

| 項目名 | 説明 |
|--------|------|
| Runner ID | Runnerの一意識別子 |
| Runner名 | Runnerの短縮名（先頭8文字のSHA） |

### 割り当て済みプロジェクト一覧

| 項目名 | 説明 |
|--------|------|
| プロジェクトアバター | プロジェクトのアイコン画像 |
| プロジェクト名 | プロジェクトのフルパス |
| オーナーバッジ | Runnerのオーナープロジェクトを示すバッジ |
| プロジェクト説明 | プロジェクトの説明文 |
| 割り当て解除ボタン | プロジェクトとの関連を解除するボタン |

### 未割り当てプロジェクト一覧

| 項目名 | 説明 |
|--------|------|
| プロジェクトアバター | プロジェクトのアイコン画像 |
| プロジェクト名 | プロジェクトのフルパス |
| プロジェクト説明 | プロジェクトの説明文 |
| 割り当てボタン | Runnerを割り当てるボタン |

## イベント仕様

### 1-Runner設定更新

**トリガー**: Runner設定フォームの保存ボタン押下

**処理フロー**:
1. フロントエンドのVueコンポーネント（js-admin-runner-edit）からAPI呼び出し
2. `Ci::Runners::UpdateRunnerService`を通じてRunner情報を更新
3. 成功時：編集画面にリダイレクト
4. 失敗時：エラーメッセージを表示し、詳細画面を再表示

### 2-プロジェクト検索

**トリガー**: 検索フォームの送信

**処理フロー**:
1. GETリクエストで`search`パラメータを送信
2. `Project.search`メソッドで名前空間を含む検索を実行
3. 既に割り当て済みのプロジェクトを除外
4. 結果を30件ずつページネーションして表示

### 3-プロジェクト割り当て

**トリガー**: 未割り当てプロジェクトの「Assign」ボタン押下

**処理フロー**:
1. POSTリクエストで`runner_id`を含むフォームを送信
2. `RunnerProject`レコードを作成
3. 割り当て済みプロジェクト一覧を更新

### 4-プロジェクト割り当て解除

**トリガー**: 割り当て済みプロジェクトの「Unassign」ボタン押下

**処理フロー**:
1. DELETEリクエストで対象の`runner_project`を削除
2. 割り当て済みプロジェクト一覧から除外
3. オーナープロジェクトは解除不可

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| Runner設定更新 | ci_runners | UPDATE | Runnerの設定情報を更新 |
| プロジェクト割り当て | ci_runner_projects | INSERT | Runner-Project関連を作成 |
| プロジェクト割り当て解除 | ci_runner_projects | DELETE | Runner-Project関連を削除 |
| タグ更新 | taggings, tags | INSERT/DELETE | タグ情報を更新 |

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

#### ci_runners

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | description | フォーム入力値 | |
| UPDATE | active | フォーム入力値 | |
| UPDATE | run_untagged | フォーム入力値 | |
| UPDATE | locked | フォーム入力値 | |
| UPDATE | access_level | フォーム入力値 | 0: not_protected, 1: ref_protected |
| UPDATE | maximum_timeout | 秒数に変換した値 | human_readable形式から変換 |
| UPDATE | updated_at | 現在時刻 | |

#### ci_runner_projects

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | runner_id | 対象RunnerのID | |
| INSERT | project_id | 割り当て対象プロジェクトのID | |
| DELETE | id | 対象runner_projectのID | オーナー以外のみ削除可能 |

## メッセージ仕様

| 種別 | 条件 | メッセージ |
|------|------|----------|
| 成功 | Runner更新成功時 | (リダイレクトのみ) |
| エラー | バリデーションエラー | 各フィールドのエラーメッセージを表示 |

## 例外処理

| 状態 | 処理 |
|------|------|
| Runnerが見つからない | 404エラー画面を表示 |
| 権限不足 | アクセス拒否画面にリダイレクト |
| 更新失敗 | エラーメッセージを表示し、詳細画面を再表示 |

## 備考

- プロジェクト割り当てセクションは、`project_type`のRunnerの場合のみ表示される
- Runner設定の編集はVueコンポーネント（`js-admin-runner-edit`）で実装されている
- Gitlab.com環境では、`public_projects_minutes_cost_factor`と`private_projects_minutes_cost_factor`も編集可能

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | runner.rb | `app/models/ci/runner.rb` | Runnerモデルの属性、関連、バリデーション |
| 1-2 | runner_project.rb | `app/models/ci/runner_project.rb` | Runner-Project関連モデル |

**読解のコツ**: `FORM_EDITABLE`定数で編集可能な属性を確認。`runner_type`enumでRunnerの種類を理解する。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | runners_controller.rb | `app/controllers/admin/runners_controller.rb` | editアクションとupdateアクション |

**主要処理フロー**:
1. **行20-22**: `edit`アクション - `assign_projects`メソッドでプロジェクト一覧を取得
2. **行30-38**: `update`アクション - `UpdateRunnerService`を呼び出してRunner情報を更新
3. **行69-80**: `assign_projects`メソッド - 検索とページネーションを含むプロジェクト一覧取得

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | edit.html.haml | `app/views/admin/runners/edit.html.haml` | 画面レイアウト、Vueマウントポイント |
| 3-2 | _project.html.haml | `app/views/admin/runners/_project.html.haml` | プロジェクト一覧アイテムのパーシャル |

**主要処理フロー**:
- **行7**: `#js-admin-runner-edit` - VueコンポーネントのマウントポイントでRunner設定編集UI
- **行9-43**: プロジェクトタイプRunner用の割り当て管理セクション

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | update_runner_service.rb | `app/services/ci/runners/update_runner_service.rb` | Runner更新ロジック |

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

```
Admin::RunnersController#edit
    │
    ├─ runner (before_action)
    │      └─ Ci::Runner.find(params[:id])
    │
    └─ assign_projects
           ├─ Project.search(params[:search])
           └─ Project.id_not_in(runner_projects_ids)

Admin::RunnersController#update
    │
    └─ Ci::Runners::UpdateRunnerService#execute
           └─ @runner.update(runner_params)
```

### データフロー図

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

Runner ID ──────▶ Ci::Runner.find ──────────────▶ @runner

search パラメータ ──▶ Project.search ─────────────▶ @projects
                          │
                          └─ id_not_in(runner_project_ids)
                          └─ page/per(30)

Runner params ─────▶ UpdateRunnerService ──────▶ 更新済み@runner
                          │
                          └─ runner.update(params)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| runners_controller.rb | `app/controllers/admin/runners_controller.rb` | コントローラー | リクエスト処理 |
| edit.html.haml | `app/views/admin/runners/edit.html.haml` | テンプレート | 画面表示 |
| _project.html.haml | `app/views/admin/runners/_project.html.haml` | パーシャル | プロジェクト一覧アイテム |
| runner.rb | `app/models/ci/runner.rb` | モデル | Runnerデータモデル |
| runner_project.rb | `app/models/ci/runner_project.rb` | モデル | Runner-Project関連 |
| update_runner_service.rb | `app/services/ci/runners/update_runner_service.rb` | サービス | 更新ロジック |
| admin.rb | `config/routes/admin.rb` | ルーティング | URL定義 |
