# 機能設計書 18-doom ci

## 概要

本ドキュメントは、Doom EmacsのCI/CDコマンド「doom ci」の機能設計を定義する。このコマンドは、継続的インテグレーション・継続的デリバリー向けのテスト・検証機能を提供する。

### 本機能の処理概要

doom ciは、Doomの開発プロセスを自動化するためのCI/CD向けコマンド群である。コミットメッセージのリント、Gitフックのデプロイ、プッシュ前の検証などを提供する。

**業務上の目的・背景**：Doom Emacsは厳格なコミット規約（Conventional Commits）を採用しており、すべてのコントリビューターがこの規約に従う必要がある。doom ciコマンドは、この規約への準拠を自動的に検証し、開発プロセスの品質を維持する。また、Gitフックを通じて、不適切なコミットがリポジトリに入るのを防ぐ。

**機能の利用シーン**：
- コミット時のメッセージ検証（commit-msgフック）
- プッシュ前のWIP/fixupコミット検出（pre-pushフック）
- CI環境でのコミット履歴検証
- Gitフックの初期設定

**主要な処理内容**：
1. コミットメッセージの構文解析
2. コミットタイプの検証（feat, fix, docs等）
3. スコープの検証
4. メッセージ長とフォーマットの検証
5. トレーラー（Fix:, Ref:等）の検証
6. WIP/fixup/squashコミットの検出

**関連システム・外部連携**：
- git: フック実行、コミット情報取得
- GitHub: PR/issue参照形式

**権限による制御**：特になし。

## 関連画面

本機能はCLIコマンドであり、GUIの画面は持たない。

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | ターミナル | 主画面 | コマンドライン実行、検証結果表示 |

## 機能種別

検証処理 / CI/CD / コミット規約チェック

## 入力仕様

### 入力パラメータ

**doom ci** (親コマンド)
| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| なし | - | - | :partial tにより部分コマンド | - |

**doom ci deploy-hooks**
| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| --force | フラグ | No | 既存フックを上書き | - |

**doom ci lint-commits**
| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| from | 文字列 | Yes | 開始コミット | 有効なgit ref |
| to | 文字列 | No | 終了コミット | 有効なgit ref |

**doom ci hook commit-msg**
| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| file | パス | Yes | コミットメッセージファイル | 有効なファイルパス |

**doom ci hook pre-push**
| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| remote | 文字列 | Yes | リモート名 | - |
| url | 文字列 | Yes | リモートURL | - |

### 入力データソース

- コミットメッセージファイル
- git logの出力
- 標準入力（pre-pushフック用）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| リント結果 | メッセージ | 警告・エラーの一覧 |
| 終了コード | 数値 | 0:成功、1:失敗 |

### 出力先

- 標準出力: 検証結果
- 標準エラー: エラーメッセージ

## 処理フロー

### 処理シーケンス（lint-commits）

```
1. コミット情報の取得
   └─ git logで対象コミットを取得

2. 各コミットの解析
   └─ doom-ci--parse-commitでコミットメッセージを解析
   └─ :type, :scopes, :subject, :body, :trailers等を抽出

3. 検証ルールの適用
   └─ doom-ci-commit-rulesの各ルールを適用
   └─ fail!, warn!, skip!で結果を記録

4. 結果の集計と表示
   └─ 警告数とエラー数を集計
   └─ エラーがある場合は終了コード1
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[コミット取得]
    B --> C[コミットループ]
    C --> D[メッセージ解析]
    D --> E[ルール検証ループ]
    E --> F{skip?}
    F -->|Yes| G[次のコミットへ]
    F -->|No| H{fail?}
    H -->|Yes| I[エラー記録]
    H -->|No| J{warn?}
    I --> K{次のルール?}
    J -->|Yes| L[警告記録]
    J -->|No| K
    L --> K
    K -->|Yes| E
    K -->|No| G
    G --> M{次のコミット?}
    M -->|Yes| C
    M -->|No| N[結果集計]
    N --> O{エラーあり?}
    O -->|Yes| P[終了コード1]
    O -->|No| Q[成功]
    P --> R[終了]
    Q --> R
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | コミットタイプ必須 | 有効なタイプ（feat, fix等）が必要 | 常時 |
| BR-02 | サブジェクト長制限 | 72文字以下、理想は50文字以下 | 常時 |
| BR-03 | ボディ行長制限 | 72文字以下（URL等は例外） | 常時 |
| BR-04 | スコープ順序 | スコープは辞書順でソート | 常時 |
| BR-05 | BREAKING CHANGE | !付きの場合、ボディにBREAKING CHANGE:が必要 | !付きコミット |
| BR-06 | WIP禁止 | main/masterへのpush時、WIP/fixup/squashコミットを禁止 | pre-push時 |

### 有効なコミットタイプ（doom-ci-commit-types）

```elisp
'(bump dev docs feat fix merge nit perf refactor release revert test tweak)
```

### 有効なトレーラーキー（doom-ci-commit-trailer-keys）

```elisp
'(("Fix" ref hash url)
  ("Ref" ref hash url)
  ("Close" ref)
  ("Revert" ref hash)
  ("Amend" ref hash)
  ("Co-authored-by" name)
  ("Signed-off-by" name))
```

### 計算ロジック

**コミットメッセージ解析**:
```elisp
;; サブジェクト行のパース
(looking-at "^\\([a-zA-Z0-9_-]+\\)\\(!?\\)\\(?:(\\([^)]+\\))\\)?: \\([^\n]+\\)")
;; :type, :bang, :scopes, :summary を抽出
```

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

本機能はデータベースを使用しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 検証エラー | コミットメッセージが規約に違反 | メッセージを修正 |
| - | 警告 | 推奨事項への非準拠 | 可能であれば修正 |

### リトライ仕様

コミットメッセージを修正して再コミット。

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

読み取り専用の検証処理のため、トランザクション管理は不要。

## パフォーマンス要件

- 単一コミットの検証は瞬時
- 大量のコミット履歴検証は時間がかかる可能性

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

- Gitフックは#o700のパーミッションで作成

## 備考

- Conventional Commits規約に基づく
- doom installから自動的にフックがデプロイされる

---

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

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

### 推奨読解順序

#### Step 1: 設定変数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ci.el | `lisp/cli/ci.el` | 6-56行目の変数定義 |

**主要処理フロー**:
- **6-16行目**: doom-ci-commit-trailer-keys - 有効なトレーラーキー
- **18-26行目**: doom-ci-commit-trailer-types - トレーラー値の形式
- **28-30行目**: doom-ci-commit-types - 有効なコミットタイプ
- **32-36行目**: doom-ci-commit-scopeless-types - スコープ不要のタイプ
- **38-56行目**: doom-ci-commit-scopes - 有効なスコープ定義

#### Step 2: 検証ルールを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ci.el | `lisp/cli/ci.el` | 58-244行目のdoom-ci-commit-rules |

**読解のコツ**: 各ルールは`lambda!`マクロで定義され、キーワード引数（:type, :subject等）でコミット情報を受け取る。`fail!`でエラー、`warn!`で警告、`skip!`でスキップを報告。

**主要ルール**:
- **60-63行目**: fixup/squash/WIPコミットのスキップ
- **65-78行目**: サブジェクト長の検証
- **80-85行目**: タイプの有効性検証
- **140-149行目**: BREAKING CHANGEの検証

#### Step 3: コマンド定義を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ci.el | `lisp/cli/ci.el` | 250-360行目のコマンド群 |

**主要処理フロー**:
- **251-253行目**: 親コマンド定義（:partial t）
- **256-285行目**: deploy-hooksコマンド
- **288-308行目**: lint-commitsコマンド
- **311-324行目**: hook commit-msgコマンド
- **327-360行目**: hook pre-pushコマンド

#### Step 4: 解析関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | ci.el | `lisp/cli/ci.el` | 366-467行目のヘルパー関数 |

**主要処理フロー**:
- **366-370行目**: doom-ci-enforce-scopeless-types
- **373-405行目**: doom-ci--parse-commit
- **407-423行目**: doom-ci--parse-bumps
- **425-467行目**: doom-ci--lint

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

```
doom ci (defcli! :partial)
    │
    ├─ doom ci deploy-hooks (defcli!)
    │      ├─ sh! "git" "rev-parse"
    │      ├─ sh! "git" "config"
    │      └─ with-temp-file (フック生成)
    │
    ├─ doom ci lint-commits (defcli!)
    │      ├─ doom-call-process "git" "log"
    │      └─ doom-ci--lint
    │
    ├─ doom ci hook commit-msg (defcli!)
    │      ├─ insert-file-contents
    │      └─ doom-ci--lint
    │
    └─ doom ci hook pre-push (defcli!)
           ├─ read-from-minibuffer
           └─ doom-call-process "git" "rev-list"

doom-ci--lint
    │
    ├─ doom-ci--parse-commit
    │
    └─ doom-ci-commit-rules (各ルール適用)
           ├─ fail!
           ├─ warn!
           └─ skip!
```

### データフロー図

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

コミットメッセージ     ───▶  doom-ci--parse-commit ───▶  plist
                                    │
                                    │
                              (:type :bang :scopes
                               :subject :summary
                               :body :trailers :bumps)
                                    │
                                    ▼
plist               ───▶  doom-ci-commit-rules ───▶  fail!/warn!/skip!
                                    │
                                    │
                              各ルール適用
                                    │
                                    ▼
                              結果集計     ───▶  終了コード
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ci.el | `lisp/cli/ci.el` | ソース | ciコマンドの主実装 |
| doom-cli.el | `lisp/doom-cli.el` | ソース | CLIフレームワーク |
| install.el | `lisp/cli/install.el` | ソース | フックデプロイの呼び出し元 |
