# バッチ設計書 14-test:e2e:ci

## 概要

本ドキュメントは、Decap CMSプロジェクトにおけるCI環境向けE2Eテスト実行バッチ `test:e2e:ci` の設計仕様を定義する。本バッチはデモサイトをビルドし、cypress/run.mjs によるマシン分割並列実行でCypress E2Eテストを高速に実行する。

### 本バッチの処理概要

本バッチは、CI環境（GitHub Actions）でE2Eテストを効率的に実行するためのスクリプトである。No.13 test:e2e と同様にデモサイトのビルドとCypressテストを行うが、cypress/run.mjs スクリプトを使用してテストスペックを複数マシンに分割し、並列実行することでCI実行時間を短縮する。

**業務上の目的・背景**：E2Eテストは実行時間が長いため、CIパイプラインのボトルネックになりやすい。本バッチはMACHINE_INDEX/MACHINE_COUNT環境変数によるシャーディングメカニズムを備え、GitHub Actionsのマトリクス戦略と組み合わせることで4台のマシンに分散してテストを実行する。これにより、CI全体の実行時間を約1/4に短縮している。

**バッチの実行タイミング**：GitHub ActionsのNode CIワークフローにおいて、main/masterブランチへのpush時またはPR時に自動実行される。changesジョブでwebsite以外のファイル変更が検出された場合のみトリガーされる。

**主要な処理内容**：
1. `npm run build:demo` - 全パッケージをビルドし、decap-cmsのdistをdev-test/dist/にコピー
2. `npm run test:e2e:run-ci` - HTTPサーバー起動後、cypress/run.mjs でシャーディング実行
   - `test:e2e:serve` - http-server -c-1 dev-test をポート8080で起動
   - `test:e2e:exec-ci` - node cypress/run.mjs でスペックを分割して並列実行

**前後の処理との関連**：build-unitジョブ（No.12 test:ci）とは独立したe2eジョブとして並列実行される。ビルドキャッシュ（Nxキャッシュ、Cypressバイナリキャッシュ）をactions/cacheで管理している。テスト失敗時にはcypress/screenshots/とcypress/videos/がアーティファクトとしてアップロードされる。

**影響範囲**：dev-test/dist/ にビルド成果物が出力される。テスト自体はモックサーバーを使用するため外部サービスへの影響はない。4台のマトリクスマシンで並列実行される。

## バッチ種別

テスト実行（CI環境向けE2Eテスト - 並列シャーディング実行）

## 実行スケジュール

| 項目 | 内容 |
|-----|------|
| 実行頻度 | イベント駆動 |
| 実行時刻 | イベント発生時 |
| 実行曜日 | なし |
| 実行日 | なし |
| トリガー | main/masterブランチへのpush、PRのopened/synchronize/reopened |

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| Node.js | Node.js 24.x がインストールされていること |
| 依存パッケージ | `npm ci` で依存関係（Cypressバイナリ含む）がインストール済みであること |
| パス変更検出 | dorny/paths-filter で website 以外のファイル変更が検出されていること |
| GitHub Actions | マトリクス戦略で machine: [1,2,3,4] が設定されていること |

### 実行可否判定

GitHub Actionsのchangesジョブにおいて、`dorny/paths-filter` により `!website/**` パターンに一致するファイル変更が検出された場合のみ実行される（`needs.changes.outputs.cms == 'true'`）。

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | デフォルト値 | 説明 |
|-------------|-----|-----|-------------|------|
| MACHINE_INDEX | 環境変数 | Yes | なし | 現在のマシン番号（1〜4） |
| MACHINE_COUNT | 環境変数 | Yes | なし | 総マシン数（4） |
| CI_BUILD_ID | 環境変数 | No | GITHUB_RUN_ID-GITHUB_RUN_ATTEMPT | Cypress並列実行のビルドID |
| CYPRESS_RECORD_KEY | 環境変数 | No | シークレット | Cypress Dashboard記録用キー |
| NODE_OPTIONS | 環境変数 | No | --max-old-space-size=4096 | Node.jsメモリ上限設定 |
| TZ | 環境変数 | No | Europe/Amsterdam | タイムゾーン設定 |

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| packages/*/src/** | ソースコード | ビルド対象の全パッケージソースコード |
| cypress/e2e/*spec*.js | テストコード | CypressE2Eテストスペックファイル |
| cypress/run.mjs | スクリプト | シャーディング・並列実行制御スクリプト |
| cypress.config.ts | 設定ファイル | Cypress設定 |
| cypress/plugins/** | プラグイン | バックエンド別のCypressプラグイン設定 |

## 出力仕様

### 出力データ

| 出力先 | 形式 | 説明 |
|-------|------|------|
| dev-test/dist/ | JavaScript/CSS | ビルド済みデモサイト成果物 |
| 標準出力 | テキスト | ビルドログ、テスト結果、シャーディング情報 |
| cypress/screenshots/ | PNG | テスト失敗時のスクリーンショット |
| cypress/videos/ | MP4 | テスト実行録画（設定により無効の場合あり） |
| GitHub Actions Artifacts | ZIP | テスト失敗時のスクリーンショット・動画 |
| プロセス終了コード | 数値 | 0: 成功、1以上: 失敗 |

### 出力ファイル仕様

| 項目 | 内容 |
|-----|------|
| ファイル名 | cypress-results-{machine番号} |
| 出力先 | GitHub Actions Artifacts（テスト失敗時のみ） |
| 内容 | cypress/screenshots, cypress/videos |

## 処理フロー

### 処理シーケンス

```
1. build:demo実行
   ├─ build:esm - 全パッケージのESMビルド実行
   ├─ build - 全パッケージのUMDビルド実行
   └─ ncp - packages/decap-cms/dist を dev-test/dist/ にコピー
2. test:e2e:run-ci実行（start-server-and-test）
   ├─ test:e2e:serve - http-server -c-1 dev-test をポート8080で起動
   ├─ ポート8080の準備完了を待機
   └─ test:e2e:exec-ci - node cypress/run.mjs を実行
3. cypress/run.mjs のシャーディングロジック
   ├─ globbyでcypress/e2e/*spec*.jsを検索
   ├─ MACHINE_INDEX/MACHINE_COUNT で担当スペックを算出
   │   ├─ specsPerMachine = Math.floor(specs.length / machineCount)
   │   ├─ 最後のマシンは残りの全スペックを担当
   │   └─ --spec オプションで担当スペックを指定
   └─ cypress run --browser chrome --headless --spec <担当スペック> を実行
4. テスト失敗時: スクリーンショット・動画をアーティファクトとしてアップロード
```

### フローチャート

```mermaid
flowchart TD
    A[GitHub Actions トリガー] --> A1{パス変更検出}
    A1 -->|website以外の変更あり| B[npm ci]
    A1 -->|変更なし| Z2[スキップ]
    B --> C[build:demo実行]
    C --> D{ビルド成功?}
    D -->|失敗| Z[エラー終了]
    D -->|成功| E[http-server起動 - ポート8080]
    E --> F[cypress/run.mjs実行]
    F --> F1[globbyでspecファイル検索]
    F1 --> F2{MACHINE_INDEX/MACHINE_COUNT設定?}
    F2 -->|あり| F3[スペックをシャーディング]
    F2 -->|なし| F4[Cypress Dashboard並列モード]
    F3 --> G[cypress run --spec 担当スペック]
    F4 --> G2[cypress run --record --parallel]
    G --> H{テスト成功?}
    G2 --> H
    H -->|失敗| I[アーティファクトアップロード]
    I --> Z
    H -->|成功| J[バッチ正常終了]
```

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

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

本バッチはデータベースへのアクセスを行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 1 | ビルドエラー | パッケージのビルド失敗 | ビルドエラーを修正してPRを更新 |
| 1 | スペック未検出 | cypress/e2e/*spec*.jsに一致するファイルがない | テストファイルの配置を確認 |
| 1 | テスト失敗 | Cypressテストケースの失敗 | アーティファクトのスクリーンショットを確認し修正 |
| 1 | タイムアウト | テスト実行が1時間を超過 | テストの最適化またはマシン数の増加を検討 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | runMode: 4回（cypress.config.ts設定） |
| リトライ間隔 | 即時 |
| リトライ対象エラー | テストケースの失敗（Cypressビルトインリトライ） |
| タイムアウト | cypress/run.mjs で1時間（60 * 60 * 1000 ms） |

### 障害時対応

テスト失敗時はGitHub ActionsのArtifactsからcypress-results-{machine番号}をダウンロードしてスクリーンショット・動画を確認する。fail-fast: true 設定により、1台のマシンで失敗した場合は他のマシンの実行もキャンセルされる。

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

| 項目 | 内容 |
|-----|------|
| トランザクション範囲 | なし |
| コミットタイミング | なし |
| ロールバック条件 | なし |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | cypress/e2e/ 配下の全specファイルを4マシンで分割 |
| 目標処理時間 | 1時間以内（execa timeout設定） |
| メモリ使用量上限 | 4096MB（NODE_OPTIONS=--max-old-space-size=4096） |

## 排他制御

GitHub Actionsのconcurrency設定により、同一ワークフロー・同一refの実行は前回の実行をキャンセルして最新のみ実行される。各マトリクスマシン（1〜4）は独立したランナーで実行されるため相互に競合しない。

## ログ出力

| ログ種別 | 出力タイミング | 出力内容 |
|---------|--------------|---------|
| 開始ログ | シャーディング開始時 | `Sharding specs manually: machine X/Y running Z specs` |
| 進捗ログ | テスト中 | Cypressのテスト実行ログ、各specの結果 |
| 終了ログ | テスト終了時 | テスト結果サマリー |
| エラーログ | テスト失敗時 | 失敗したspecの詳細、スクリーンショットパス |
| Cypressコマンドログ | 実行前 | `Running Cypress with args: run --browser chrome --headless --spec ...` |

## 監視・アラート

| 監視項目 | 閾値 | アラート先 |
|---------|-----|----------|
| ジョブ失敗 | 1回 | GitHub PRステータスチェック |
| 実行タイムアウト | 1時間（execa設定） | GitHub Actions |
| アーティファクト | テスト失敗時 | GitHub Actions Artifacts |

## 備考

- 本バッチは `npm run test:e2e:ci` コマンドで実行される
- シャーディングロジック: specsPerMachine = Math.floor(specs.length / machineCount)、最後のマシンが残余スペックを担当
- MACHINE_INDEX/MACHINE_COUNTが未設定の場合は、Cypress Dashboardの--record --parallelモードにフォールバック
- CI_BUILD_IDは GITHUB_RUN_ID-GITHUB_RUN_ATTEMPT 形式でワークフローから設定
- execa timeout: 1時間（60 * 60 * 1000 ms）
- テスト失敗時のみcypress/screenshots, cypress/videosをアーティファクトとしてアップロード（if: failure()）
- Nxキャッシュ（.nx/cache）とCypressバイナリ（~/.cache/Cypress）はactions/cacheで永続化
- TZ=Europe/Amsterdam でタイムゾーンが固定される
