# 画面設計書 163-Runner新規登録

## 概要

本ドキュメントはGitLabのグループRunner新規登録画面の設計仕様を記載したものである。

### 本画面の処理概要

グループに新しいCI/CD Runnerを登録するための画面である。Runner作成ウィザードを通じて、Runnerの基本設定（タグ、説明、保護モード等）を行い、登録トークンを発行する。発行されたトークンを使用して、実際のRunner環境でGitLab Runnerをインストール・登録する。

**業務上の目的・背景**：CI/CDパイプラインを実行するためには、ジョブを処理するRunnerが必要である。本画面により、グループ管理者がUI操作で簡単にRunnerを作成し、グループ配下のすべてのプロジェクトで利用可能なRunnerを準備できる。従来の登録トークン方式に加え、ユーザー認証ベースのRunner作成が可能。

**画面へのアクセス方法**：グループRunner一覧画面から「New group runner」ボタンをクリック、または直接URL `/{group_path}/-/runners/new` にアクセスする。

**主要な操作・処理内容**：
1. プラットフォーム選択（Linux、macOS、Windows、Docker等）
2. Runnerタグの設定
3. Runner説明の入力
4. 保護モード（protected branch only）の設定
5. 未タグジョブ実行許可の設定
6. ロック設定（現在プロジェクト専用）
7. 最大タイムアウトの設定
8. Runner作成の実行
9. 登録コマンドの表示・コピー

**画面遷移**：
- 遷移元：Runner一覧画面
- 遷移先：Runner登録完了画面（registerアクション）、Runner一覧画面

**権限による表示制御**：
- `create_runners`権限：本画面へのアクセスが可能

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 51 | Runnerレジストレーション | 主機能 | グループRunnerの登録 |

## 画面種別

登録

## URL/ルーティング

- パス: `/{group_path}/-/runners/new`
- コントローラー: `Groups::RunnersController#new`
- HTTPメソッド: GET

## 入出力項目

| 項目名 | 項目ID | 入出力 | データ型 | 必須 | 説明 |
|--------|--------|--------|----------|------|------|
| グループID | group_id | 入力 | GlobalID | 必須 | 対象グループのグローバルID |
| プラットフォーム | platform | 入力 | String | 任意 | linux/macos/windows/docker |
| タグ | tag_list | 入力 | Array[String] | 任意 | Runnerに設定するタグ |
| 説明 | description | 入力 | String | 任意 | Runnerの説明文 |
| 保護モード | access_level | 入力 | String | 任意 | not_protected/ref_protected |
| 未タグジョブ実行 | run_untagged | 入力 | Boolean | 任意 | タグなしジョブを実行するか |
| ロック | locked | 入力 | Boolean | 任意 | プロジェクトにロックするか |
| 最大タイムアウト | maximum_timeout | 入力 | Integer | 任意 | ジョブ最大実行時間（秒） |

## 表示項目

| 項目名 | データソース | 説明 |
|--------|-------------|------|
| プラットフォーム選択 | 固定値 | Linux、macOS、Windows、Dockerから選択 |
| タグ入力 | ユーザー入力 | カンマ区切りでタグを入力 |
| 説明入力 | ユーザー入力 | Runnerの説明文 |
| 保護モードチェック | ユーザー入力 | 保護ブランチのみで実行 |
| 未タグジョブチェック | ユーザー入力 | タグなしジョブを実行 |
| ロックチェック | ユーザー入力 | 現在のグループにロック |
| 最大タイムアウト | ユーザー入力 | ジョブ最大実行時間 |
| 登録コマンド | 生成値 | Runner登録用コマンド |

## イベント仕様

### 1-Runner作成ボタン押下

新規Runnerを作成し、登録トークンを発行する。

- トリガー: 「Create runner」ボタンクリック
- 処理: GraphQL mutation `runnerCreate`を実行
- 遷移先: Runner登録画面（registerアクション）
- 結果: ci_runnersテーブルにレコード作成、トークン発行

### 2-キャンセルボタン押下

Runner一覧画面へ戻る。

- トリガー: 「Cancel」ボタンクリック
- 遷移先: `/{group_path}/-/runners`

### 3-プラットフォーム選択変更

選択されたプラットフォームに応じたインストールコマンドを表示。

- トリガー: プラットフォームタブクリック
- 処理: 表示コマンドの切り替え

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| Runner作成 | ci_runners | INSERT | 新規Runnerレコード作成 |
| Runner作成 | ci_runner_namespaces | INSERT | グループとの関連付け |

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

#### ci_runners

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | runner_type | 2 (group_type) | グループRunner |
| INSERT | description | ユーザー入力値 | 説明 |
| INSERT | active | true | 初期値は有効 |
| INSERT | access_level | ユーザー入力値 | 0:not_protected / 1:ref_protected |
| INSERT | run_untagged | ユーザー入力値 | デフォルトtrue |
| INSERT | locked | ユーザー入力値 | デフォルトfalse |
| INSERT | maximum_timeout | ユーザー入力値 | 秒単位 |
| INSERT | token | 自動生成 | 登録トークン |
| INSERT | token_expires_at | 計算値 | トークン有効期限 |
| INSERT | creation_state | 0 (started) | 作成開始状態 |
| INSERT | registration_type | 1 (authenticated_user) | ユーザー認証方式 |
| INSERT | creator_id | current_user.id | 作成者 |
| INSERT | organization_id | group.organization_id | 組織ID |

#### ci_runner_namespaces

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | runner_id | 作成されたRunner ID | Runner参照 |
| INSERT | namespace_id | グループID | グループ参照 |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|---------------|---------|
| MSG001 | 成功 | Runner created successfully | Runner作成成功時 |
| MSG002 | エラー | Failed to create runner | Runner作成失敗時 |
| MSG003 | 情報 | Copy the registration token | 登録トークン表示時 |
| MSG004 | 警告 | This token can only be viewed once | トークン表示警告 |

## 例外処理

| 例外条件 | 処理内容 |
|---------|---------|
| 権限不足 | 404ページを表示 |
| グループ未存在 | 404ページを表示 |
| バリデーションエラー | エラーメッセージを表示 |
| タグ数上限超過 | エラーメッセージ表示（50個まで） |
| タイムアウト値不正 | エラーメッセージ表示（10分以上） |

## 備考

- 本画面はVue.jsコンポーネントによるSPA構成
- Runner作成はGraphQL mutationで実行
- トークンは作成直後のみ表示可能（セキュリティ上の理由）
- トークンプレフィックスは`glrt-`（GitLab Runner Token）
- 登録完了までの有効期間は1時間（REGISTRATION_AVAILABILITY_TIME）

---

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

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

### 推奨読解順序

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

Runner作成時のデータ構造とバリデーションを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | runner.rb | `app/models/ci/runner.rb` | バリデーション、enum定義、トークン生成 |

**読解のコツ**:
- `FORM_EDITABLE`（行91）で編集可能な項目を確認
- `validates :maximum_timeout`（行272-273）でタイムアウトバリデーション確認
- `TAG_LIST_MAX_LENGTH`（行94）でタグ上限確認
- `REGISTRATION_AVAILABILITY_TIME`（行82）で登録有効期間確認

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

HAMLテンプレートとコントローラーの処理起点を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | new.html.haml | `app/views/groups/runners/new.html.haml` | Vueマウントポイント、group_idをdata属性で設定 |
| 2-2 | runners_controller.rb | `app/controllers/groups/runners_controller.rb` | newアクション、authorize_create_runners! |

**主要処理フロー**:
1. **行38**: `new`アクションは空（Vueで表示処理）
2. **行66-69**: `authorize_create_runners!`で権限チェック
3. **行5**: `#js-group-new-runner`要素にgroup_idを設定

#### Step 3: フロントエンド初期化を理解する

Vue.jsアプリケーションの初期化処理を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | index.js | `app/assets/javascripts/pages/groups/runners/new/index.js` | エントリーポイント |
| 3-2 | group_new_runner/index.js | `app/assets/javascripts/ci/runner/group_new_runner/index.js` | Vueアプリ初期化 |

**主要処理フロー**:
- `initGroupNewRunner`関数でgroup_idをGlobalIDとして取得

#### Step 4: Runner作成サービスを理解する

Runner作成のビジネスロジックを確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | create_runner_service.rb | `app/services/ci/runners/create_runner_service.rb` | Runner作成サービス |

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

```
Groups::RunnersController#new
    │
    ├─ authorize_create_runners! (認可チェック)
    │
    └─ View: new.html.haml
           └─ JavaScript: initGroupNewRunner()
                  └─ Vue: GroupNewRunnerApp
                         │
                         └─ GraphQL mutation: runnerCreate
                                │
                                └─ Ci::Runners::CreateRunnerService
                                       ├─ Ci::Runner.create
                                       └─ Ci::RunnerNamespace.create
```

### データフロー図

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

URLリクエスト ───▶ RunnersController#new ───▶ HAMLテンプレート
                         │
                         ▼
                  認可チェック
                         │
                         ▼
                  Vue初期化 ───▶ フォーム表示
                         │
                         ▼
ユーザー入力 ───▶ GraphQL mutation ───▶ CreateRunnerService
                         │
                         ▼
                  ci_runners INSERT ───▶ 登録トークン発行
                         │
                         ▼
                  Runner登録画面へ遷移
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| new.html.haml | `app/views/groups/runners/new.html.haml` | テンプレート | Vueマウントポイント定義 |
| runners_controller.rb | `app/controllers/groups/runners_controller.rb` | コントローラー | リクエスト処理・認可 |
| runner.rb | `app/models/ci/runner.rb` | モデル | Runnerデータ定義・バリデーション |
| create_runner_service.rb | `app/services/ci/runners/create_runner_service.rb` | サービス | Runner作成ロジック |
| index.js | `app/assets/javascripts/ci/runner/group_new_runner/index.js` | JavaScript | Vue初期化 |
