# 通知設計書 15-GitHub Actionsアノテーション（エラー）

## 概要

本ドキュメントは、Jestテストフレームワークにおける GitHub Actions エラーアノテーション機能の設計について記載する。GitHubActionsReporterクラスの`generateAnnotations`メソッドによって実装され、テスト失敗時にGitHub Actions特有の形式でエラーアノテーションを出力する。

### 本通知の処理概要

**業務上の目的・背景**：GitHub Actionsで実行されるCI/CDパイプラインにおいて、テスト失敗の情報をGitHubのUI上で直接確認できるようにする。アノテーションを使用することで、プルリクエストの「Files changed」タブやActionsのログ上で、失敗したテストの位置（ファイル名、行番号）とエラーメッセージを直接表示できる。これにより、開発者はすぐに問題箇所を特定できる。

**通知の送信タイミング**：各テストファイルの実行完了時に`onTestResult`メソッドが呼び出され、その中で`generateAnnotations`が実行される。失敗したテストケースの`failureMessages`があれば、それぞれに対してエラーアノテーションが出力される。

**通知の受信者**：GitHub ActionsのCI/CDパイプラインを通じて、プルリクエストの作成者およびレビュアー。GitHubのWeb UI上でアノテーションとして表示される。

**通知内容の概要**：`::error`形式でファイル名、行番号、タイトル（テスト名）、エラーメッセージを含むアノテーションを出力する。スタックトレースから抽出したファイル位置情報を含む。

**期待されるアクション**：開発者はGitHub上でアノテーションを確認し、失敗したテストの原因を調査・修正する。

## 通知種別

CI統合（GitHub Actionsアノテーション）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期 |
| 優先度 | 高（エラー） |
| リトライ | なし |

### 送信先決定ロジック

標準出力（this.log）に`::error`形式で出力。GitHub Actionsランナーがこの形式を解釈してアノテーションを生成する。

## 通知テンプレート

### コンソール出力形式

| 項目 | 内容 |
|-----|------|
| 出力先 | 標準出力（stdout） |
| 形式 | GitHub Actionsワークフローコマンド |

### 本文テンプレート

```
::error file={ファイル名},line={行番号},title={テスト名}::{エラーメッセージ}
```

### エラーメッセージ例

```
::error file=src/utils/math.ts,line=42,title=Math utils > should add numbers correctly::Expected 5 to equal 6%0A%0A    at Object.<anonymous> (src/utils/__tests__/math.test.ts:15:12)
```

### 特殊文字エスケープ

| 文字 | エスケープ後 |
|-----|------------|
| % | %25 |
| \r | %0D |
| \n | %0A |

### 添付ファイル

なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| file | 失敗が発生したファイルパス | topFrame.file | No |
| line | 失敗が発生した行番号 | topFrame.line | No |
| title | テスト名（ancestorTitles + title） | result.ancestorTitles, result.title | Yes |
| message | エラーメッセージとスタックトレース | failureMessage + formatPath | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| テスト完了後 | onTestResult → generateAnnotations | failureMessagesが存在 | GitHubActionsReporter.generateAnnotations()で実行 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| 失敗テストなし | result.failureMessagesが空の場合 |
| GitHub Actions環境外 | GitHubActionsReporterが設定されていない場合 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[onTestResult呼び出し] --> B[generateAnnotations]
    B --> C{testResults配列ループ}
    C --> D{retryReasons存在?}
    D -->|Yes| E[警告アノテーション生成]
    D -->|No| F{failureMessages存在?}
    E --> F
    F -->|Yes| G[エラーアノテーション生成]
    F -->|No| H[次のテスト結果]
    G --> I[#getMessageDetails]
    I --> J[separateMessageFromStack]
    J --> K[getStackTraceLines]
    K --> L[getTopFrame]
    L --> M[formatPath]
    M --> N[#createAnnotation]
    N --> O[特殊文字エスケープ]
    O --> P[this.log出力]
    P --> H
    H --> C
    C -->|完了| Q[終了]
```

## データベース参照・更新仕様

### 参照テーブル一覧

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

### テーブル別参照項目詳細

該当なし

### 更新テーブル一覧

該当なし

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| スタックトレース解析失敗 | topFrameがnullの場合 | file/lineをundefinedとして出力 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0（リトライなし） |
| リトライ間隔 | - |
| リトライ対象エラー | - |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | なし |
| 1日あたり上限 | なし |

### 配信時間帯

制限なし

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

- アノテーションはGitHub UIで公開されるため、機密情報を含むエラーメッセージに注意
- スタックトレースにはファイルパスが含まれる
- ANSIエスケープシーケンスはstripAnsiで除去される

## 備考

- GitHub Actionsのワークフローコマンド形式に準拠
- jest-message-utilを使用してスタックトレースを解析
- titleSeparatorは` > `（Unicode 203A使用）

---

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

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

### 推奨読解順序

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

アノテーション生成で扱うデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | GitHubActionsReporter.ts | `packages/jest-reporters/src/GitHubActionsReporter.ts` | L29-35: AnnotationOptions型 |
| 1-2 | GitHubActionsReporter.ts | `packages/jest-reporters/src/GitHubActionsReporter.ts` | L37: titleSeparator定数 |

**読解のコツ**: AnnotationOptionsはfile, line, message, title, typeを持ち、type は 'error' | 'warning' のいずれか。

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

処理の起点となるonTestResultメソッドを特定。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | GitHubActionsReporter.ts | `packages/jest-reporters/src/GitHubActionsReporter.ts` | L86-98: onTestResultメソッド |

**主要処理フロー**:
1. **L91**: `generateAnnotations`を呼び出し
2. **L92-94**: silentでなければ`printFullResult`を呼び出し
3. **L95-97**: 最後のテストスイートなら`printFailedTestLogs`を呼び出し

#### Step 3: アノテーション生成処理

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | GitHubActionsReporter.ts | `packages/jest-reporters/src/GitHubActionsReporter.ts` | L100-126: generateAnnotationsメソッド |

**主要処理フロー**:
- **L104-107**: testResultsをループ、titleを構築（ancestorTitles + title）
- **L109-116**: retryReasonsがあれば警告アノテーション（type: 'warning'）
- **L118-124**: failureMessagesがあればエラーアノテーション（type: 'error'）

#### Step 4: メッセージ詳細の取得

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | GitHubActionsReporter.ts | `packages/jest-reporters/src/GitHubActionsReporter.ts` | L128-144: #getMessageDetailsメソッド |

**主要処理フロー**:
- **L129**: separateMessageFromStackでメッセージとスタックを分離
- **L131-132**: getStackTraceLines, getTopFrameでスタック情報を抽出
- **L134-136**: formatPathでスタックラインを正規化
- **L137**: messageTextを構築

#### Step 5: アノテーション出力処理

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | GitHubActionsReporter.ts | `packages/jest-reporters/src/GitHubActionsReporter.ts` | L146-158: #createAnnotationメソッド |

**主要処理フロー**:
- **L147-153**: 特殊文字をURLエンコード風にエスケープ（%25, %0D, %0A）
- **L155-157**: `::error file=...,line=...,title=...::message`形式で出力

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

```
GitHubActionsReporter.onTestResult (L86)
    │
    ├─ generateAnnotations (L100)
    │      │
    │      ├─ titleの構築 (L104-107)
    │      │
    │      ├─ [retryReasons] #createAnnotation (type: 'warning')
    │      │
    │      └─ [failureMessages] #createAnnotation (type: 'error')
    │             │
    │             ├─ #getMessageDetails (L128)
    │             │      │
    │             │      ├─ separateMessageFromStack (jest-message-util)
    │             │      │
    │             │      ├─ getStackTraceLines (jest-message-util)
    │             │      │
    │             │      ├─ getTopFrame (jest-message-util)
    │             │      │
    │             │      └─ formatPath (jest-message-util)
    │             │
    │             └─ #createAnnotation (L146)
    │                    │
    │                    ├─ stripAnsi (L147)
    │                    │
    │                    ├─ 特殊文字エスケープ (L149-152)
    │                    │
    │                    └─ this.log (L155-157)
    │
    ├─ printFullResult (L93) [silent=false]
    │
    └─ printFailedTestLogs (L96) [最後のスイート]
```

### データフロー図

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

TestResult ─────────────▶ generateAnnotations
  │                              │
  │ testResults                  │
  │ (AssertionResult[])          ▼
  │                        各テスト結果ループ
  │                              │
  │ failureMessages ─────────────┤
  │                              │
  │                              ▼
  │                      #getMessageDetails
  │                              │
  │                    ┌─────────┼─────────┐
  │                    │         │         │
  │                    ▼         ▼         ▼
  │               message    stack    topFrame
  │                    │         │         │
  │                    └─────────┼─────────┘
  │                              │
  │                              ▼
  │                      #createAnnotation
  │                              │
  │                              ▼
  │                      特殊文字エスケープ
  │                              │
  │                              ▼
  └─────────────────────────▶ stdout
                        ::error file=...,line=...,title=::...
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| GitHubActionsReporter.ts | `packages/jest-reporters/src/GitHubActionsReporter.ts` | ソース | メイン実装ファイル |
| BaseReporter.ts | `packages/jest-reporters/src/BaseReporter.ts` | ソース | Reporterインターフェースの基底実装 |
| jest-message-util | `packages/jest-message-util/` | パッケージ | スタックトレース解析ユーティリティ |
| @jest/test-result | `packages/jest-test-result/` | 型定義 | AssertionResult等の型定義 |
