Design
Context¶
現在のGitHub Actionsワークフロー構成には以下の問題がある:
- test.yml: PR to main と push で発火し、テストを実行
- deploy.yml: すべてのブランチの push で発火し、test/lint/deployを実行
- 結果: PR to main では両ワークフローが発火し、テストが重複実行される(3-4ジョブが並行実行)
- パスフィルターなし: ドキュメントのみの変更でもフルパイプラインが実行される
- 存在しないファイル参照: deploy.ymlが
scripts/seed/index.jsonを参照しているが、このファイルは存在しない
この問題を解決するため、3ファイル構成に再構築し、責務を明確に分離する。
Goals / Non-Goals¶
Goals:
- CI効率の向上: 重複実行の完全排除、適切なパスフィルターによる最適化
- 明確な責務分離: CI(品質保証)、本番デプロイ、開発デプロイの3つに分離
- リソース最適化: feature branchのPRがない限り、CIを実行しない
- コスト削減: GitHub Actionsの実行時間とジョブ数を削減
- 拡張性: 将来のE2Eテスト統合に備えた構造(deploy-dev.ymlに拡張ポイント)
Non-Goals:
- E2Eテストの実装: 今回は準備のみ、実装は将来の課題
- デプロイ先の変更: Azure Blob Storageへのデプロイは継続
- ビルドプロセスの変更: 既存のViteビルド設定を維持
- ワークフロー以外のCI/CD改善: パッケージマネージャーやキャッシュ戦略の変更は対象外
Decisions¶
1. 3ファイル構成の採用¶
決定: ci.yml + deploy.yml + deploy-dev.yml の3ファイル構成
理由:
- 責務の明確な分離: CI(品質保証)とデプロイ(環境反映)を完全に分離
- concurrency制御の粒度向上: CIはPR単位、デプロイは環境単位で制御
- 可読性と保守性: 各ワークフローの目的が明確で、複雑な条件分岐が不要
代替案:
- 1ファイルで複雑な条件分岐: 可読性・保守性が低下、concurrency制御が困難
- 2ファイル構成(CI + Deploy統合): dev/prod環境の制御が複雑化
2. ci.ymlでのジョブ並列実行¶
決定: test/lint/buildの3ジョブを並列実行(needs なし)
理由:
- 実行時間短縮: 最長ジョブの時間のみで完了(テストが通常最長)
- ジョブ間の依存関係なし: 各ジョブは独立して実行可能
- 早期フィードバック: lintやbuildエラーを待たずに検出
代替案:
- 直列実行: 実行時間が長くなり、フィードバック速度が低下
3. パスフィルターの厳格化¶
決定: src/**, tests/**, e2e/**, 設定ファイル(package.json, pnpm-lock.yaml等)のみをトリガー対象に
理由:
- 不要な実行を防ぐ: ドキュメント変更(README.md等)でCIが走らない
- フィードバック速度向上: 実際にコード品質に影響する変更のみを検証
- コスト削減: ムダなGitHub Actionsの実行を削減
代替案:
- パスフィルターなし: すべての変更でCIが実行され、リソース浪費
- 緩いフィルター: ドキュメント変更も含めるとムダな実行が残る
4. deploy-dev.ymlを手動トリガーのみに¶
決定: workflow_dispatch のみで発火、自動トリガーなし
理由:
- 開発環境の制御性向上: 意図しないデプロイを防止
- 将来のE2Eテスト統合の準備: 手動実行→E2Eテスト→承認のフローを想定
- リソース節約: feature branchの push で開発デプロイが走らない
代替案:
- feature branchの push で自動デプロイ: ムダな実行が多く、制御が困難
- PR to main で自動デプロイ: 本番デプロイと重複し、混乱を招く
5. concurrency設定の戦略¶
決定:
- ci.yml:
group: ci-${{ github.ref }},cancel-in-progress: true→ PR単位でグループ化、新しいpushで古い実行をキャンセル - deploy.yml:
group: deploy-prod,cancel-in-progress: false→ 本番デプロイは完全性を保証、キャンセルしない - deploy-dev.yml:
group: deploy-dev,cancel-in-progress: true→ 開発デプロイは最新のみ実行、古い実行はキャンセル可能
理由:
- CI: 最新のコードのみ検証すればよく、古い実行は不要
- 本番デプロイ: デプロイの完全性を保証し、中途半端な状態を避ける
- 開発デプロイ: 最新のデプロイのみ有効で、古い実行はリソース浪費
6. 初期データ配置ステップの削除¶
決定: deploy.ymlの scripts/seed/index.json 参照ステップを完全削除
理由:
- ファイルが存在しない: 現在のリポジトリに該当ファイルがなく、ステップが失敗する
- 不要な処理: データは別の方法で管理されている
代替案:
- ファイルを作成: 不要なファイルを追加することになり、保守負担が増える
Risks / Trade-offs¶
[リスク] パスフィルターが厳格すぎると、必要なビルドがスキップされる可能性
- 軽減策: 設定ファイル(package.json, pnpm-lock.yaml, vite.config.js, .eslintrc.cjs)もフィルターに含める
- 軽減策: ワークフロー自身(
.github/workflows/ci.yml)の変更もトリガーに含める
[リスク] 手動トリガーのみの開発デプロイは利便性が低下
- 軽減策: GitHub Actions UIから簡単に実行可能
- 将来の改善: E2Eテスト統合時に自動化フローを再検討
[トレードオフ] 3ファイル構成は管理対象が増える
- メリット: 明確な責務分離と保守性向上が、ファイル数増加のデメリットを上回る
- 軽減策: 各ワークフローの目的を明確にドキュメント化
[リスク] ci.ymlとdeploy.ymlの両方がmainブランチで発火し、並列実行される
- 影響: リソース使用量は変わらないものの、両方の成功が必要となる
- メリット: CIとデプロイは独立しており、デプロイ失敗時もCI結果は保持される
[リスク] concurrency設定のミスによる意図しないキャンセルやデプロイ競合
- 軽減策: deploy-prodはキャンセルしない設定で、デプロイの完全性を保証
- 軽減策: 初回デプロイ後、動作を監視して問題があれば調整