# 機能設計書 20-タグ管理

## 概要

本ドキュメントは、GitLabにおけるタグ管理機能の設計仕様を定義する。タグの作成、削除、一覧表示機能について、処理フロー、入出力仕様、ビジネスルールを記載する。

### 本機能の処理概要

タグ管理機能は、Gitリポジトリのタグを管理する機能である。開発者はタグの一覧確認、新規作成、削除を行うことができる。

**業務上の目的・背景**：Git開発ワークフローにおいて、タグはリリースバージョンのマーキングに使用される。バージョン管理やリリース管理の基盤として、効率的なタグ操作を提供する。

**機能の利用シーン**：
- 新しいバージョンのリリース時にタグを作成する場合
- リリースノート付きのアノテーションタグを作成する場合
- 不要なタグを削除して整理する場合
- タグに関連するパイプライン状態を確認する場合
- リリース情報を確認する場合

**主要な処理内容**：
1. タグ一覧の取得と表示
2. タグの作成（軽量タグ/アノテーションタグ）
3. タグの削除
4. タグに関連するリリース情報の表示
5. タグのパイプライン状態表示

**関連システム・外部連携**：
- Gitalyサーバーとの連携（Git操作）
- CI/CDパイプラインとの連携（ステータス表示）
- リリース機能との連携

**権限による制御**：
- タグ一覧閲覧：read_code権限
- タグ作成/削除：admin_tag権限

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 37 | タグ一覧 | 主画面 | タグの一覧表示 |
| 38 | タグ新規作成 | 主画面 | 新規タグの作成処理 |

## 機能種別

CRUD操作（Create/Read/Delete）

## 入力仕様

### 入力パラメータ（一覧表示）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| namespace_id | String | Yes | 名前空間パス | 存在する名前空間 |
| project_id | String | Yes | プロジェクトパス | 存在するプロジェクト |
| sort | String | No | ソート順 | updated_desc/updated_asc/name_asc/name_desc |
| search | String | No | 検索文字列 | - |
| page | Integer | No | ページ番号 | 正の整数 |

### 入力パラメータ（作成）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| tag_name | String | Yes | タグ名 | 有効なタグ名 |
| ref | String | Yes | 基点となるref | 存在するref |
| message | String | No | タグメッセージ | - |
| release_description | String | No | リリース説明 | - |

### 入力データソース

- 画面入力：タグ名、基点ref、メッセージ、リリース説明
- URLパラメータ：プロジェクト識別子、フィルタ条件

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| tags | Array | タグ一覧 |
| tag | Gitlab::Git::Tag | 作成されたタグ |
| releases | Array | 関連リリース情報 |
| tag_pipeline_statuses | Hash | パイプライン状態 |

### 出力先

- 画面表示：タグ一覧UI
- Atom Feed：タグ一覧のRSS

## 処理フロー

### 処理シーケンス（一覧表示）

```
1. 一覧表示リクエスト
   └─ TagsController#indexが呼び出される

2. 権限チェック
   └─ authorize_read_code!で閲覧権限を確認

3. タグ取得
   └─ TagsFinderでタグ取得

4. 関連情報取得
   ├─ リリース情報取得
   └─ パイプライン状態取得

5. レスポンス生成
   └─ HTML/Atom形式で返却
```

### 処理シーケンス（作成）

```
1. 作成リクエスト
   └─ TagsController#createが呼び出される

2. 権限チェック
   └─ authorize_admin_tag!で作成権限を確認

3. タグ作成
   └─ Tags::CreateService#execute
      └─ repository.add_tag

4. リリース作成（オプション）
   └─ release_descriptionがある場合
      └─ Releases::CreateService#execute

5. 結果処理
   ├─ 成功: タグ詳細画面にリダイレクト
   └─ 失敗: エラー表示
```

### フローチャート

```mermaid
flowchart TD
    A[タグ操作リクエスト] --> B{操作種別?}
    B -->|一覧| C{閲覧権限?}
    C -->|No| D[403エラー]
    C -->|Yes| E[タグ取得]
    E --> F[リリース情報取得]
    F --> G[パイプライン状態取得]
    G --> H[一覧表示]

    B -->|作成| I{作成権限?}
    I -->|No| D
    I -->|Yes| J{ref有効?}
    J -->|No| K[refエラー]
    J -->|Yes| L{タグ名有効?}
    L -->|No| M[名前エラー]
    L -->|Yes| N[タグ作成]
    N --> O{リリース説明あり?}
    O -->|Yes| P[リリース作成]
    O -->|No| Q[タグ詳細へリダイレクト]
    P --> Q

    B -->|削除| R{削除権限?}
    R -->|No| D
    R -->|Yes| S[タグ削除]
    S --> T[リリース削除]
    T --> U[アーティファクトロック解除]
    U --> V[一覧へリダイレクト]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 閲覧権限 | read_code権限が必要 | 一覧表示時 |
| BR-02 | 作成権限 | admin_tag権限が必要 | 作成時 |
| BR-03 | 削除権限 | admin_tag権限が必要 | 削除時 |
| BR-04 | タグ名規則 | Gitの命名規則に準拠 | 作成時 |
| BR-05 | ref必須 | 作成時に基点refが必要 | 作成時 |
| BR-06 | リリース連動 | タグ削除時に関連リリースも削除 | 削除時 |
| BR-07 | 重複禁止 | 同名タグは作成不可 | 作成時 |

### 計算ロジック

- **タグソート**: 更新日順または名前順でソート
- **リリース関連付け**: タグ名でリリースを関連付け

## データベース操作仕様

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| リリース取得 | releases | SELECT | 関連リリース取得 |
| リリース作成 | releases | INSERT | タグ作成時のリリース作成 |
| リリース削除 | releases | DELETE | タグ削除時のリリース削除 |

### Gitalyへのリクエスト

| 操作 | 内容 | 備考 |
|-----|------|------|
| FindAllTags | タグ一覧取得 | - |
| UserCreateTag | タグ作成 | - |
| UserDeleteTag | タグ削除 | - |
| FindTag | タグ検索 | 個別取得時 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 403 | Forbidden | 権限がない | 権限を確認 |
| 404 | Not Found | タグが存在しない | タグ名を確認 |
| 400 | Bad Request | refが空 | refを指定 |
| 400 | Bad Request | タグ名不正 | 名前を修正 |
| 409 | Conflict | タグが既に存在 | 別の名前を指定 |

### リトライ仕様

- エラー時は入力内容を修正して再試行

## トランザクション仕様

- Gitへのタグ操作は原子的に実行
- リリース削除はタグ削除後に非同期実行

## パフォーマンス要件

- タグ数が多い場合はページネーション
- 署名データのバッチロード対応

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

- 作成/削除権限の厳格なチェック
- タグ名のサニタイズ
- 署名付きタグの署名検証

## 備考

- タグ作成時にリリースも同時作成可能（release_description指定時）
- タグ削除時に関連リリースも自動削除
- タグ削除時にCI/CDアーティファクトのロック解除が実行される

---

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

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

### 推奨読解順序

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

Gitタグオブジェクトを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | tag.rb | `lib/gitlab/git/tag.rb` | Gitタグオブジェクトの構造 |

**読解のコツ**: タグはtarget（コミットSHA）、name（タグ名）、message（アノテーション）を持つ。

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

コントローラーのタグ操作処理を確認する。

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

**主要処理フロー**:
1. **16-46行目**: indexアクション、タグ一覧取得
2. **49-61行目**: showアクション、タグ詳細表示
3. **63-94行目**: createアクション、タグ作成（リリース連携含む）
4. **96-109行目**: destroyアクション、タグ削除

#### Step 3: タグ作成サービスを理解する

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

**主要処理フロー**:
- **5-9行目**: execute、バリデーション（target空、タグ名検証）
- **17行目**: repository.add_tag呼び出し
- **18-24行目**: エラーハンドリング（重複、PreReceiveError）

#### Step 4: タグ削除サービスを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | destroy_service.rb | `app/services/tags/destroy_service.rb` | タグ削除ロジック |

**主要処理フロー**:
- **5-15行目**: execute、タグ検索と権限チェック
- **17行目**: repository.rm_tag呼び出し
- **21行目**: destroy_releases、関連リリース削除
- **23行目**: unlock_artifacts、アーティファクトロック解除

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

```
Projects::TagsController#index
    │
    ├─ authorize_read_code! (権限チェック)
    │
    ├─ TagsFinder#execute
    │      └─ repository.tags_sorted_by
    │
    ├─ ReleasesFinder (リリース情報)
    │
    └─ Ci::CommitStatusesFinder (パイプライン状態)

Projects::TagsController#create
    │
    ├─ authorize_admin_tag! (権限チェック)
    │
    ├─ Tags::CreateService#execute
    │      ├─ Gitlab::GitRefValidator.validate (名前検証)
    │      └─ repository.add_tag (タグ作成)
    │
    └─ Releases::CreateService#execute (リリース作成、オプション)

Projects::TagsController#destroy
    │
    ├─ authorize_admin_tag! (権限チェック)
    │
    └─ Tags::DestroyService#execute
           ├─ repository.rm_tag (タグ削除)
           ├─ Releases::DestroyService#execute (リリース削除)
           └─ Ci::RefDeleteUnlockArtifactsWorker (アーティファクトロック解除)
```

### データフロー図

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

フィルタ条件 ───▶ TagsController ───▶ タグ一覧
                       │
                       ▼
               TagsFinder
                       │
                       ▼
               Gitaly RPC ───▶ タグデータ
                       │
                       ▼
               リリース情報取得
                       │
                       ▼
               パイプライン状態取得
                       │
                       ▼
               一覧表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| tags_controller.rb | `app/controllers/projects/tags_controller.rb` | コントローラー | タグ操作のエントリーポイント |
| create_service.rb | `app/services/tags/create_service.rb` | サービス | タグ作成処理 |
| destroy_service.rb | `app/services/tags/destroy_service.rb` | サービス | タグ削除処理 |
| tags_finder.rb | `app/finders/tags_finder.rb` | Finder | タグ検索 |
| releases_finder.rb | `app/finders/releases_finder.rb` | Finder | リリース検索 |
| create_service.rb | `app/services/releases/create_service.rb` | サービス | リリース作成（タグ作成時） |
| destroy_service.rb | `app/services/releases/destroy_service.rb` | サービス | リリース削除（タグ削除時） |
