# 通知設計書 17-GitHub Actionsグループ出力

## 概要

本ドキュメントは、Jestテストフレームワークにおける GitHub Actions グループ出力機能の設計について記載する。GitHubActionsReporterクラスの`printResultTree`メソッドによって実装され、テスト結果をGitHub Actions特有の形式でグループ化して出力する。

### 本通知の処理概要

**業務上の目的・背景**：GitHub Actionsのログは大量になりがちで、必要な情報を見つけることが困難になる。グループ機能を使用することで、成功したテストは折りたたみ表示、失敗したテストは展開表示することで、開発者が重要な情報に素早くアクセスできるようにする。テスト結果はツリー形式で階層化され、describeブロックの構造を反映する。

**通知の送信タイミング**：各テストファイルの実行完了時に`onTestResult`メソッドが呼び出され、silentオプションがfalseの場合に`printFullResult`が呼び出される。その中で`printResultTree`がテスト結果をグループ化して出力する。

**通知の受信者**：GitHub ActionsのCI/CDパイプラインを通じて、ログを確認する開発者。GitHub ActionsのWeb UI上でグループとして表示される。

**通知内容の概要**：`::group::`と`::endgroup::`形式でテスト結果をグループ化。PASSしたテストは緑のインバース表示、FAILしたテストは赤のインバース表示。各テストケースには成功/失敗/pending/todoのアイコンと実行時間が表示される。

**期待されるアクション**：開発者はログを確認し、失敗したテストに注目して問題を調査する。成功したテストはデフォルトで折りたたまれているため、展開して詳細を確認することもできる。

## 通知種別

CI統合（GitHub Actionsグループ出力）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期 |
| 優先度 | 中 |
| リトライ | なし |

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

標準出力（this.log）に`::group::`/`::endgroup::`形式で出力。GitHub Actionsランナーがこの形式を解釈してグループを生成する。

## 通知テンプレート

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

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

### グループ開始テンプレート

```
::group::{タイトル}
```

### グループ終了テンプレート

```
::endgroup::
```

### テスト結果テンプレート（成功）

```
::group::PASS {テストファイルパス} ({実行時間} ms)
  {describeブロック名}
    {アイコン} {テスト名} ({実行時間} ms)
::endgroup::
```

### テスト結果テンプレート（失敗）

```
  FAIL {テストファイルパス} ({実行時間} ms)
    {describeブロック名}
      {アイコン} {テスト名} ({実行時間} ms)
```

### ステータスアイコン一覧

| ステータス | アイコン | 色 |
|----------|--------|-----|
| passed | ICONS.success | 緑 |
| failed | ICONS.failed | 赤 |
| pending/skipped | ICONS.pending | 黄 |
| todo | ICONS.todo | マゼンタ |

### 添付ファイル

なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| testFilePath | テストファイルパス | results.testFilePath | Yes |
| testResults | テスト結果配列 | results.testResults | Yes |
| perfStats | パフォーマンス統計 | results.perfStats | Yes |
| runtime | 実行時間（ミリ秒） | perfStats.runtime | Yes |
| slow | 実行が遅いかどうか | perfStats.slow | Yes |
| passed | テストが全て成功したか | resultTree.passed | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| テスト完了後 | onTestResult → printFullResult | silentオプション=false | GitHubActionsReporter.printResultTree()で実行 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| silentオプション有効 | reporterOptionsのsilentがtrueの場合（デフォルトはtrue） |
| GitHub Actions環境外 | GitHubActionsReporterが設定されていない場合 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[onTestResult呼び出し] --> B{silent=false?}
    B -->|No| Z[終了]
    B -->|Yes| C[printFullResult]
    C --> D[getResultTree]
    D --> E[printResultTree]
    E --> F{passed?}
    F -->|Yes| G[startGroup: PASS]
    F -->|No| H[log: FAIL]
    G --> I[consoleLog出力]
    H --> J[recursivePrintResultTree]
    I --> J
    J --> K{children処理}
    K --> L{leaf?}
    L -->|Yes| M[ステータスアイコン出力]
    L -->|No| N{passed?}
    N -->|Yes| O{alreadyGrouped?}
    N -->|No| P[log: ノード名]
    O -->|Yes| Q[log: ノード名]
    O -->|No| R[startGroup: ノード名]
    Q --> S[再帰処理]
    R --> S
    P --> S
    S --> T[endGroup（必要時）]
    M --> S
    T --> U[次の子要素]
    U --> K
    K -->|完了| V[終了]
```

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

### 参照テーブル一覧

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

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

該当なし

### 更新テーブル一覧

該当なし

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 不正なツリー構造 | leafにpassedが、nodeにdurationがある場合 | Error throw |

### リトライ仕様

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

## 配信設定

### レート制限

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

### 配信時間帯

制限なし

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

- テスト名やコンソール出力に機密情報が含まれる可能性に注意
- ログはGitHub Actionsの履歴として保持される

## 備考

- デフォルトでsilent=trueのため、明示的にsilent=falseを設定する必要がある
- 成功したテストはグループ化されて折りたたみ可能
- 失敗したテストはグループ化されず展開表示
- consoleLogがある場合、silentでなければテスト結果とともに出力
- 最後のテストスイートでprintFailedTestLogsが呼ばれ、失敗テストのログをまとめて表示

---

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

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

### 推奨読解順序

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

グループ出力で扱うデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | GitHubActionsReporter.ts | `packages/jest-reporters/src/GitHubActionsReporter.ts` | L40-45: PerformanceInfo型 |
| 1-2 | GitHubActionsReporter.ts | `packages/jest-reporters/src/GitHubActionsReporter.ts` | L47-52: ResultTreeLeaf型 |
| 1-3 | GitHubActionsReporter.ts | `packages/jest-reporters/src/GitHubActionsReporter.ts` | L54-58: ResultTreeNode型 |
| 1-4 | GitHubActionsReporter.ts | `packages/jest-reporters/src/GitHubActionsReporter.ts` | L60-65: ResultTree型 |

**読解のコツ**: ResultTreeは再帰的な構造で、Leafは個別テスト、Nodeはdescribeブロックを表す。

#### 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` | L176-186: printFullResultメソッド |
| 3-2 | GitHubActionsReporter.ts | `packages/jest-reporters/src/GitHubActionsReporter.ts` | L212-257: getResultTreeメソッド |

**主要処理フロー**:
- **L177-179**: rootDirからテストパスを相対化
- **L180-184**: getResultTreeでツリー構造を構築
- **L185**: printResultTreeで出力

#### Step 4: ツリーの出力処理

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

**主要処理フロー**:
- **L322-329**: パフォーマンス情報の表示（遅い場合は赤のインバース）
- **L330-340**: passed=trueならstartGroupでグループ開始（PASS表示）
- **L341-348**: passed=falseならログ出力のみ（FAIL表示）
- **L337-339**: 各子要素をrecursivePrintResultTreeで処理

#### Step 5: 再帰的なツリー出力

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

**主要処理フロー**:
- **L356-385**: Leafの場合（children.length === 0）
- **L366-380**: ステータスに応じたアイコン表示
- **L386-409**: Nodeの場合（childrenあり）
- **L390-401**: passedでalreadyGroupedでなければstartGroup
- **L403-408**: failedの場合はグループ化せずlog出力

#### Step 6: グループ開始/終了

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 6-1 | GitHubActionsReporter.ts | `packages/jest-reporters/src/GitHubActionsReporter.ts` | L446-452: startGroup/endGroupメソッド |

**主要処理フロー**:
- **L446-448**: `::group::${title}`を出力
- **L450-452**: `::endgroup::`を出力

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

```
GitHubActionsReporter.onTestResult (L86)
    │
    ├─ generateAnnotations (L91)
    │
    └─ printFullResult (L176) [silent=false]
           │
           ├─ rootDirから相対パス計算 (L177-179)
           │
           ├─ getResultTree (L212)
           │      │
           │      └─ getResultChildren (L259) [再帰]
           │
           └─ printResultTree (L317)
                  │
                  ├─ [passed] startGroup: PASS (L331-332)
                  │
                  ├─ [failed] log: FAIL (L342-343)
                  │
                  └─ recursivePrintResultTree (L351) [再帰]
                         │
                         ├─ [Leaf] ステータスアイコン出力 (L366-380)
                         │
                         ├─ [Node, passed, !alreadyGrouped] startGroup (L397)
                         │
                         ├─ [Node, passed, alreadyGrouped] log (L392)
                         │
                         ├─ [Node, failed] log (L404)
                         │
                         └─ [Node] endGroup (L401) [alreadyGrouped=false]
```

### データフロー図

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

TestResult ─────────────▶ printFullResult
  │                              │
  │ testResults                  │
  │ testFilePath                 │
  │ perfStats                    │
  │                              ▼
  │                       getResultTree
  │                              │
  │                              ▼
  │                       ResultTree
  │                              │
  │         ┌────────────────────┴────────────────────┐
  │         │                                         │
  │         ▼                                         ▼
  │    ResultTreeNode                           ResultTreeLeaf
  │    (describe)                               (test case)
  │         │                                         │
  │         └────────────────────┬────────────────────┘
  │                              │
  │                              ▼
  │                       printResultTree
  │                              │
  │                    ┌─────────┼─────────┐
  │                    │         │         │
  │                    ▼         ▼         ▼
  │              ::group::     log    ::endgroup::
  │                    │         │         │
  └────────────────────┴─────────┴─────────┘
                              │
                              ▼
                           stdout
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| GitHubActionsReporter.ts | `packages/jest-reporters/src/GitHubActionsReporter.ts` | ソース | メイン実装ファイル |
| BaseReporter.ts | `packages/jest-reporters/src/BaseReporter.ts` | ソース | Reporterインターフェースの基底実装 |
| @jest/console | `packages/jest-console/` | パッケージ | getConsoleOutput関数 |
| jest-util | `packages/jest-util/` | パッケージ | specialChars.ICONS |
