# 画面設計書 38-タグ新規作成

## 概要

本ドキュメントは、GitLabのリポジトリに新規タグを作成する画面（タグ新規作成画面）の設計を記述したものである。

### 本画面の処理概要

本画面は、既存のブランチ、タグ、またはコミットSHAを基点として新しいタグを作成するための画面である。タグ名と作成元を指定し、オプションでメッセージ（注釈）を付けて新しいタグを作成できる。

**業務上の目的・背景**：ソフトウェアリリース管理において、タグは特定のバージョンをマーキングする重要な機能である。本画面は、ローカル環境やGit CLIを使用せずに、Webインターフェースから直接タグを作成できる機能を提供する。注釈付きタグを作成することで、リリースノートやバージョン情報を記録できる。

**画面へのアクセス方法**：
- タグ一覧画面の「New tag」ボタンをクリック
- URL直接入力: `/{namespace}/{project}/-/tags/new`

**主要な操作・処理内容**：
1. 新しいタグ名の入力
2. 作成元（ブランチ/タグ/コミットSHA）の選択
3. メッセージ（注釈）の入力（オプション）
4. タグの作成実行
5. 作成されたタグの詳細画面へ遷移

**画面遷移**：
- 遷移元: タグ一覧画面
- 遷移先: タグ詳細画面、（エラー時）同画面

**権限による表示制御**：
- タグ管理権限（admin_tag）がない場合はアクセス不可

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 20 | タグ管理 | 主機能 | 新規タグの作成処理 |
| 73 | リリース作成 | 遷移先機能 | リリース作成画面への案内 |

## 画面種別

登録

## URL/ルーティング

```
GET  /{namespace}/{project}/-/tags/new
POST /{namespace}/{project}/-/tags
```

**ルート定義**: `config/routes/repository.rb`
```ruby
resources :tags, only: [:index, :show, :new, :create, :destroy]
```

## 入出力項目

| 項目名 | 入出力 | 型 | 必須 | 説明 |
|--------|--------|-----|------|------|
| namespace | 入力 | String | Yes | プロジェクトの名前空間 |
| project | 入力 | String | Yes | プロジェクト名 |
| tag_name | 入力 | String | Yes | 新しいタグ名 |
| ref | 入力 | String | Yes | 作成元の参照（ブランチ名/タグ名/コミットSHA） |
| message | 入力 | String | No | タグメッセージ（注釈付きタグ用） |
| release_description | 入力 | String | No | リリース説明（レガシーオプション） |

## 表示項目

| 項目名 | 説明 | データソース |
|--------|------|-------------|
| タグ名入力欄 | 新しいタグ名の入力 | 入力項目 |
| 作成元セレクター | ブランチ/タグ/コミットの選択 | リポジトリ情報 |
| デフォルト作成元 | 初期選択値 | params[:ref] または @project.default_branch |
| メッセージ入力欄 | タグメッセージの入力 | 入力項目 |
| エラーメッセージ | バリデーションエラー | @error |
| リリース作成案内 | リリース作成ページへのリンク | 固定テキスト |

## イベント仕様

### 1-ページ読み込み

タグ作成フォームを初期化する。

**処理フロー**:
1. タグ管理権限の確認（authorize_admin_tag!）
2. デフォルトの作成元を設定（params[:ref]またはdefault_branch）
3. 参照セレクターコンポーネント（Vue.js）を初期化

### 2-タグ名入力

新しいタグ名を入力する。

**バリデーション**:
- 必須入力（required: true）
- Git参照名として有効な文字のみ（Gitlab::GitRefValidator.validate）
- 既存タグ名との重複チェック

### 3-メッセージ入力

注釈付きタグ用のメッセージを入力する。

**処理**:
- 空白が両端からトリミングされる（message&.strip）
- メッセージありの場合は注釈付きタグとして作成

### 4-Create tagボタン押下

新しいタグを作成する。

**処理フロー**:
1. Tags::CreateServiceを呼び出し
2. 作成元（target）の検証
3. タグ名の検証（GitRefValidator）
4. リポジトリにタグを追加（repository.add_tag）
5. 成功時：タグ詳細画面へリダイレクト
6. エラー時：エラーメッセージ表示して再表示

### 5-Cancelボタン押下

タグ作成をキャンセルしてタグ一覧へ戻る。

**遷移先**: `/{namespace}/{project}/-/tags`

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| Create tag | events | INSERT | タグ作成イベントの記録 |
| Create tag | push_event_payloads | INSERT | プッシュイベント詳細 |

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

#### events

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | action | 5 (PUSHED) | プッシュアクション |
| INSERT | author_id | current_user.id | 実行ユーザー |
| INSERT | project_id | @project.id | 対象プロジェクト |

#### push_event_payloads

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | action | 1 (CREATED) | タグ作成 |
| INSERT | ref_type | 2 (TAG) | タグ参照 |
| INSERT | ref | 新タグ名 | タグ名 |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 発生条件 |
|-------------|------|---------------|----------|
| M001 | エラー | "Target is empty" | 作成元が未指定 |
| M002 | エラー | "Tag name invalid" | 無効なタグ名 |
| M003 | エラー | "Tag {tag_name} already exists" | 既存タグとの重複 |
| M004 | エラー | "Target {target} is invalid" | 無効な参照 |
| M005 | エラー | "Failed to create a tag: {tag_name}" | リポジトリエラー |

## 例外処理

| 例外 | 発生条件 | 処理内容 |
|------|---------|---------|
| 403 Forbidden | タグ管理権限なし | アクセス拒否画面表示 |
| Gitlab::Git::Repository::TagExistsError | タグ重複 | エラーメッセージ表示 |
| Gitlab::Git::PreReceiveError | pre-receiveフック失敗 | エラーメッセージ表示 |
| Gitlab::Git::Repository::NoRepository | リポジトリなし | エラーメッセージ表示 |

## 備考

- メッセージを入力すると注釈付きタグ（annotated tag）、未入力の場合は軽量タグ（lightweight tag）として作成される
- リリース作成は別画面で行うよう案内される（ページ上部にリンクあり）
- タグ名はHTMLタグが除去され、URIエンコードが解除される
- タグ作成後はタグキャッシュが無効化される（repository.expire_tags_cache）

---

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

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

### 推奨読解順序

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

タグ作成で使用されるパラメータと検証ロジックを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | create_service.rb | `app/services/tags/create_service.rb` | タグ作成ロジック |
| 1-2 | git_ref_validator.rb | `lib/gitlab/git_ref_validator.rb` | タグ名検証 |

**読解のコツ**: `Tags::CreateService`は作成元検証とタグ名検証を行った後、`repository.add_tag`を呼び出す。メッセージがある場合は注釈付きタグとして作成される。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | tags_controller.rb | `app/controllers/projects/tags_controller.rb` | createアクション |

**主要処理フロー**:
1. **63行目**: `def create` - メインアクション
2. **65行目**: エビデンスパイプラインの取得（レガシー機能）
3. **67-68行目**: `Tags::CreateService`の呼び出し
4. **70-83行目**: 成功時のリリース作成処理（レガシー）
5. **85-87行目**: タグ詳細画面へのリダイレクト
6. **88-93行目**: エラー時の再表示

#### Step 3: ビューテンプレートを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | new.html.haml | `app/views/projects/tags/new.html.haml` | フォーム全体構造 |

**主要処理フロー**:
- **1-2行目**: パンくずとページタイトル
- **3行目**: デフォルト作成元の設定
- **4-5行目**: リリース作成ページへの案内
- **7-10行目**: エラーメッセージ表示
- **12-13行目**: ページヘッダー
- **15行目**: form_tag - POSTリクエスト先
- **16-19行目**: タグ名入力欄
- **20-25行目**: 作成元セレクター（Vue.jsコンポーネント）
- **26-31行目**: メッセージ入力欄
- **33-37行目**: アクションボタン群

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | create_service.rb | `app/services/tags/create_service.rb` | タグ作成 |

**主要処理フロー**:
- **5行目**: `execute(tag_name, target, message)` - メイン処理
- **6行目**: 作成元（target）の空チェック
- **8-9行目**: タグ名の検証
- **12行目**: メッセージのトリム
- **17行目**: `repository.add_tag`でタグ作成
- **18-24行目**: 例外処理
- **27行目**: タグキャッシュの無効化

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

```
Projects::TagsController#create
    │
    ├─ find_evidence_pipeline (legacy)
    │      └─ project.ci_pipelines.for_sha
    │
    └─ Tags::CreateService#execute
           │
           ├─ validate target (blank check)
           │
           ├─ Gitlab::GitRefValidator.validate
           │
           ├─ message.strip
           │
           └─ repository.add_tag
                  │
                  ├─ Gitlab::Git::Repository#add_tag
                  │
                  └─ repository.expire_tags_cache
```

### データフロー図

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

Form Parameters ───▶ TagsController#create ───▶ Redirect / Error
  - tag_name          │
  - ref               ├─▶ Tags::CreateService
  - message           │      │
                      │      ├─▶ GitRefValidator.validate
                      │      │
                      │      └─▶ Repository#add_tag
                      │             │
                      │             └─▶ Git Repository
                      │
                      └─▶ redirect_to tag detail page
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| tags_controller.rb | `app/controllers/projects/tags_controller.rb` | コントローラー | リクエスト処理 |
| new.html.haml | `app/views/projects/tags/new.html.haml` | テンプレート | フォームビュー |
| create_service.rb | `app/services/tags/create_service.rb` | サービス | タグ作成ロジック |
| git_ref_validator.rb | `lib/gitlab/git_ref_validator.rb` | バリデーター | 参照名検証 |
| repository.rb | `config/routes/repository.rb` | ルーティング | URL定義 |
