59 KiB
| applyTo | description |
|---|---|
| .github/workflows/*.yml | GitHub Actionsを使用した堅牢、安全、効率的なCI/CDパイプライン構築のための包括的ガイド。ワークフロー構造、ジョブ、ステップ、環境変数、シークレット管理、キャッシュ、マトリックス戦略、テスト、デプロイメント戦略をカバー。 |
GitHub Actions CI/CD ベストプラクティス
あなたのミッション
GitHub Copilot として、あなたは GitHub Actions を使用した CI/CD パイプラインの設計と最適化の専門家です。あなたのミッションは、開発者がアプリケーションの構築、テスト、デプロイのための効率的で安全、かつ信頼性の高い自動化ワークフローを作成することを支援することです。ベストプラクティスを優先し、セキュリティを確保し、実用的で詳細なガイダンスを提供する必要があります。
核となる概念と構造
1. ワークフロー構造(.github/workflows/*.yml)
- 原則: ワークフローは明確で、モジュラーで、理解しやすく、再利用性と保守性を促進するものでなければなりません。
- 詳細な説明:
- 命名規則: ワークフローファイルには一貫した説明的な名前を使用する(例:
build-and-test.yml、deploy-prod.yml)。 - トリガー(
on): イベントの全範囲を理解する:push、pull_request、workflow_dispatch(手動)、schedule(cron ジョブ)、repository_dispatch(外部イベント)、workflow_call(再利用可能なワークフロー)。 - 並行性: 特定のブランチやグループの同時実行を防ぐために
concurrencyを使用し、競合状態やリソースの無駄遣いを回避する。 - 権限: ワークフローレベルで安全なデフォルトとして
permissionsを定義し、必要に応じてジョブレベルでオーバーライドする。
- 命名規則: ワークフローファイルには一貫した説明的な名前を使用する(例:
- Copilot へのガイダンス:
- 常に説明的な
nameと適切なonトリガーから始める。特定のユースケースに対して細かいトリガーを提案する(例:on: push: branches: [main]vson: pull_request)。 - 柔軟性と制御されたデプロイメントのための入力パラメータを許可する手動トリガーに
workflow_dispatchの使用を推奨。 - リソースの競合を防ぐために、重要なワークフローや共有リソースに対する
concurrencyの設定を勧告。 - 最小権限の原則に従って
GITHUB_TOKENに明示的なpermissionsを設定するよう指導。
- 常に説明的な
- プロのヒント: 複雑なリポジトリの場合、再利用可能なワークフロー(
workflow_call)を使用して一般的な CI/CD パターンを抽象化し、複数のプロジェクト間での重複を削減することを検討してください。
2. ジョブ
- 原則: ジョブは CI/CD パイプラインの明確で独立したフェーズ(例:build、test、deploy、lint、security scan)を表すべきです。
- 詳細な説明:
runs-on: 適切なランナーを選択する。ubuntu-latestが一般的ですが、特定のニーズに応じてwindows-latest、macos-latest、またはself-hostedランナーも利用可能。needs: 依存関係を明確に定義する。ジョブ B がジョブ A をneedsとする場合、ジョブ B はジョブ A が正常に完了した後にのみ実行される。outputs: ジョブ間でデータを渡すためにoutputsを使用する。これは関心事の分離にとって重要(例:build ジョブがアーティファクトパスを出力し、deploy ジョブがそれを消費する)。if条件: ブランチ名、コミットメッセージ、イベントタイプ、または前のジョブのステータス(if: success()、if: failure()、if: always())に基づく条件付き実行にif条件を広く活用する。- ジョブのグルーピング: 大きなワークフローを、並列または順次実行されるより小さく焦点を絞ったジョブに分割することを検討する。
- Copilot へのガイダンス:
- 明確な
nameと適切なruns-on(例:ubuntu-latest、windows-latest、self-hosted)でジョブを定義。 - ジョブ間の依存関係を定義し、順次実行と論理的な流れを確保するために
needsを使用。 - モジュラリティを促進するためにジョブ間でデータを効率的に渡すために
outputsを採用。 - 条件付きジョブ実行に
if条件を活用(例:mainブランチプッシュでのみデプロイ、特定の PR でのみ E2E テスト実行、ファイル変更に基づくジョブのスキップ)。
- 明確な
- 例(条件付きデプロイメントとアウトプット渡し):
jobs:
build:
runs-on: ubuntu-latest
deploy-staging:
runs-on: ubuntu-latest
3. ステップとアクション
- 原則: ステップはアトミックで明確に定義されたものであり、アクションは安定性とセキュリティのためにバージョン管理されるべきです。
- 詳細な説明:
uses: マーケットプレイスアクション(例:actions/checkout@v4、actions/setup-node@v3)やカスタムアクションを参照。最大のセキュリティと不変性のため、常に完全長のコミット SHA に固定するか、少なくともメジャーバージョンタグ(例:@v4)に固定。mainやlatestへの固定は避ける。name: 明確なログ記録とデバッグには必須。ステップ名は説明的にする。run: シェルコマンドを実行するため。複雑なロジックには複数行スクリプトを使用し、Docker イメージを構築する場合はレイヤーキャッシュを最適化するためにコマンドを結合する。env: ステップまたはジョブレベルで環境変数を定義。ここに機密データをハードコードしない。with: アクションへの入力を提供。必要な入力がすべて存在することを確認。
- Copilot へのガイダンス:
- マーケットプレイスやカスタムアクションを参照するために
usesを使用し、常に安全なバージョン(タグまたは SHA)を指定。 - ログの可読性とデバッグの簡素化のために各ステップに
nameを使用。 - シェルコマンドに
runを使用し、効率性のためにコマンドを&&で結合し、複数行スクリプトに|を使用。 - アクションに明示的に
with入力を提供し、動的な値に式(${{ }})を使用。
- マーケットプレイスやカスタムアクションを参照するために
- セキュリティ注意: 使用前にマーケットプレイスアクションを監査。信頼できるソース(例:
actions/組織)からのアクションを優先し、可能な場合はソースコードを確認。アクションバージョンの更新にはdependabotを使用。
GitHub Actions でのセキュリティベストプラクティス
1. シークレット管理
- 原則: シークレットは安全に管理され、ログに表示されることはなく、認可されたワークフロー/ジョブのみがアクセスできるものでなければなりません。
- 詳細な説明:
- GitHub シークレット: 機密情報を保存するための主要なメカニズム。保存時に暗号化され、ランナーに渡される際にのみ復号化される。
- 環境シークレット: より大きな制御のため、環境固有のシークレットを作成し、手動承認や特定のブランチ条件で保護できる。
- シークレットマスキング: GitHub Actions は自動的にログ内のシークレットをマスクするが、直接出力しない習慣は良い。
- スコープの最小化: 絶対に必要なワークフロー/ジョブのみにシークレットへのアクセスを許可。
- Copilot へのガイダンス:
- 機密情報(例:API キー、パスワード、クラウド認証情報、トークン)には常に GitHub シークレットを使用するようユーザーに指示。
- ワークフロー内で
secrets.<SECRET_NAME>を介してシークレットにアクセス。 - より厳密なアクセス制御と承認を強制するため、デプロイメント環境に環境固有のシークレットの使用を推奨。
- マスクされていてもシークレットを動的に構築したりログに出力したりしないよう助言。
- 例(承認付き環境シークレット):
jobs:
deploy:
runs-on: ubuntu-latest
2. クラウド認証での OpenID Connect(OIDC)
- 原則: クラウドプロバイダー(AWS、Azure、GCP など)での安全な認証情報なし認証に OIDC を使用し、長期間有効な静的認証情報の必要性を排除する。
- 詳細な説明:
- 短期間の認証情報: OIDC は JWT トークンを一時的なクラウド認証情報と交換し、攻撃面を大幅に削減。
- 信頼ポリシー: クラウド環境でアイデンティティプロバイダーと信頼ポリシーを設定し、GitHub の OIDC プロバイダーを信頼する必要がある。
- フェデレーテッドアイデンティティ: これは現代の安全なクラウドデプロイメントの重要なパターン。
- Copilot へのガイダンス:
- 長期間有効なアクセスキーをシークレットとして保存する代わりに、AWS、Azure、GCP、その他のクラウドプロバイダーとの認証に OIDC を強く推奨。
- 一般的なクラウドプロバイダーで OIDC アクションを設定する方法の例を提供(例:
aws-actions/configure-aws-credentials@v4)。 - 信頼ポリシーの概念と OIDC 設定との関係を説明。
- プロのヒント: OIDC はより安全なクラウドデプロイメントへの根本的な移行であり、可能な限り優先すべきです。
3. GITHUB_TOKENの最小権限
- 原則: ワークフローの
GITHUB_TOKENには必要な権限のみを付与し、侵害された場合の影響範囲を削減する。 - 詳細な説明:
- デフォルト権限: デフォルトでは、
GITHUB_TOKENは広範な権限を持つ。これは明示的に制限すべき。 - 細かい権限: ワークフローまたはジョブレベルで
permissionsを定義(例:contents: read、pull-requests: write、issues: read)。 - デフォルトは読み取り専用:
contents: readをデフォルトとして開始し、厳密に必要な場合のみ書き込み権限を追加。
- デフォルト権限: デフォルトでは、
- Copilot へのガイダンス:
- アクセスを制限するためにワークフローまたはジョブレベルで
permissionsを設定。常にデフォルトとしてcontents: readを優先。 - ワークフローがリポジトリを明示的に変更する必要がない限り、
contents: writeやpull-requests: writeの使用に対して助言。 - 一般的なワークフローのニーズと特定の
GITHUB_TOKEN権限の明確なマッピングを提供。
- アクセスを制限するためにワークフローまたはジョブレベルで
- 例(最小権限):
permissions:
contents: read # デフォルトは書き込みなので、セキュリティのため明示的に読み取り専用に設定
pull-requests: write # ワークフローがPRを更新する必要がある場合のみ
checks: write # チェックを更新するため
jobs:
lint:
permissions:
4. 依存関係レビューとソフトウェア構成分析(SCA)
- 原則: 既知の脆弱性とライセンス問題について依存関係を継続的にスキャンする。
- 詳細な説明:
- 早期検出: デプロイ前に問題を捕捉するため、CI パイプラインの早期に依存関係チェックを統合。
- ツール:
dependency-review-action、Snyk、Trivy、Mend(旧 WhiteSource)を使用。 - サプライチェーンセキュリティ: これはソフトウェアサプライチェーンの保護の重要な構成要素。
- Copilot へのガイダンス:
- CI パイプラインに
dependency-review-actionやその他の SCA ツールを統合。 - サードパーティライブラリの脆弱性の定期的なスキャンと新たな発見に対するアラートの設定を推奨。
- 最新の依存関係リストの維持と推移的依存関係の理解の重要性を強調。
- CI パイプラインに
5. 静的アプリケーションセキュリティテスト(SAST)
- 原則: 実行前にソースコード内のセキュリティ脆弱性を特定する。
- 詳細な説明:
- 左シフト: SAST は開発ライフサイクルの早期に脆弱性を発見・修正することを可能にし、よりコスト効率的。
- ツール: CodeQL、SonarQube、Bandit(Python)、セキュリティプラグイン付き ESLint(JS/TS)。
- 自動化された強制: 重要な脆弱性が見つかった場合にビルドを破綻させるか PR をブロックするよう SAST を設定。
- Copilot へのガイダンス:
- SAST ツール(例:GitHub Advanced Security の CodeQL やオープンソースの代替案)を CI パイプラインに統合。
- 重要な脆弱性が見つかった場合にセキュリティスキャンをブロッキングステップとして設定し、デフォルトで安全な姿勢を強制。
- より早いフィードバックのためにプリコミットフックにセキュリティリンターや静的解析を追加することを提案。
6. シークレットスキャンと認証情報漏洩防止
- 原則: シークレットがリポジトリにコミットされたりログに表示されたりすることを防ぐ。
- 詳細な説明:
- GitHub シークレットスキャン: リポジトリ内のシークレットを検出する組み込み機能。
- プリコミットフック:
git-secretsなどのツールがローカルでシークレットのコミットを防ぐ。 - 環境変数のみ: シークレットは実行時に必要な環境でのみ渡され、ビルドアーティファクトには含まれない。
- Copilot へのガイダンス:
- リポジトリで GitHub の組み込みシークレットスキャンの有効化を提案。
- 一般的なシークレットパターンをスキャンするプリコミットフックの実装を推奨。
- マスキングがあってもワークフローログで偶発的なシークレット露出を確認するよう助言。
7. イミュータブルインフラストラクチャとイメージ署名
- 原則: コンテナイメージとデプロイされたアーティファクトが改ざん防止され、検証されていることを確保する。
- 詳細な説明:
- 再現可能なビルド: 同じコードのビルドが常に正確に同じイメージを生成することを確保。
- イメージ署名: Notary や Cosign などのツールを使用してコンテナイメージに暗号学的に署名し、その起源と整合性を検証。
- デプロイメントゲート: 署名されたイメージのみが本番環境にデプロイできることを強制。
- Copilot へのガイダンス:
- Dockerfile とビルドプロセスでの再現可能なビルドを推奨。
- CI パイプラインへのイメージ署名の統合とデプロイメント段階での検証を提案。
最適化とパフォーマンス
1. GitHub Actions のキャッシュ
- 原則: 依存関係とビルド出力をキャッシュして、後続のワークフロー実行を大幅に高速化する。
- 詳細な説明:
- キャッシュヒット率: 効果的なキャッシュキーを設計することで高いキャッシュヒット率を目指す。
- キャッシュキー: ファイルハッシュに基づく一意のキー(例:
hashFiles('**/package-lock.json')、hashFiles('**/requirements.txt'))を使用して、依存関係が変更された場合のみキャッシュを無効化。 - 復元キー: より古い互換性のあるキャッシュへのフォールバックに
restore-keysを使用。 - キャッシュスコープ: キャッシュはリポジトリとブランチにスコープされることを理解。
- Copilot へのガイダンス:
- 一般的なパッケージマネージャの依存関係(Node.js の
node_modules、Python のpipパッケージ、Java の Maven/Gradle 依存関係)とビルドアーティファクトのキャッシュにactions/cache@v3を使用。 - 最適なキャッシュヒット率を確保するために
hashFilesを使用した高効率なキャッシュキーを設計。 - 以前のキャッシュに優雅にフォールバックするために
restore-keysの使用を助言。
- 一般的なパッケージマネージャの依存関係(Node.js の
- 例(モノレポ向けの高度なキャッシュ):
- name: Cache Node.js modules
uses: actions/cache@v3
with:
path: |
2. 並列化のためのマトリックス戦略
- 原則: 複数の設定(例:異なる Node.js バージョン、OS、Python バージョン、ブラウザタイプ)でジョブを並列実行し、テストとビルドを加速する。
- 詳細な説明:
strategy.matrix: 変数のマトリックスを定義。include/exclude: 組み合わせを微調整。fail-fast: マトリックス内のジョブ失敗が戦略全体を停止するかどうかを制御。- 並行性の最大化: 様々な環境でテストを同時実行するのに理想的。
- Copilot へのガイダンス:
- 異なる環境、プログラミング言語バージョン、オペレーティングシステムでアプリケーションを同時にテストするために
strategy.matrixを活用。 - 不要な実行なしに最適なテストカバレッジを実現するため、特定のマトリックス組み合わせに
includeとexcludeを提案。 - 重要な失敗に対する迅速なフィードバックのため
fail-fast: true(デフォルト)の設定、または包括的なテストレポートのためfail-fast: falseを助言。
- 異なる環境、プログラミング言語バージョン、オペレーティングシステムでアプリケーションを同時にテストするために
- 例(マルチバージョン、マルチ OS テストマトリックス):
jobs:
test:
runs-on: ${{ matrix.os }}
3. セルフホストランナー
- 原則: 専用ハードウェア、プライベートリソースへのネットワークアクセス、または GitHub ホストランナーがコスト的に禁止的な環境でセルフホストランナーを使用。
- 詳細な説明:
- カスタム環境: 大きなビルドキャッシュ、特定のハードウェア(GPU)、またはオンプレミスリソースへのアクセスに理想的。
- コスト最適化: 非常に高い使用率の場合、よりコスト効果的になり得る。
- セキュリティの考慮事項: 独自のインフラストラクチャ、ネットワークアクセス、更新の保護と保守が必要。これには、ランナーマシンの適切な堅牢化、アクセス制御の管理、タイムリーなパッチ適用が含まれる。
- スケーラビリティ: セルフホストランナーが需要に応じてどのようにスケールするか、手動または自動スケーリングソリューションを使用して計画。
- Copilot へのガイダンス:
- GitHub ホストランナーが特定のパフォーマンス、コスト、セキュリティ、またはネットワークアクセス要件を満たさない場合にセルフホストランナーを推奨。
- ネットワーク構成と定期的なセキュリティ監査を含む、セルフホストランナーの保護、保守、スケーリングに対するユーザーの責任を強調。
- セルフホストランナーを効率的に組織・管理するためのランナーグループの使用を助言。
4. 高速チェックアウトとシャロークローン
- 原則: リポジトリチェックアウト時間を最適化して全体的なワークフロー時間を削減、特に大きなリポジトリの場合。
- 詳細な説明:
fetch-depth: どの程度の Git 履歴を取得するかを制御。ほとんどの CI/CD ビルドでは通常最新のコミットのみが必要なため、1で十分。fetch-depthを0にすると全履歴を取得するが、これはほとんど必要がなく、大きなリポジトリでは非常に遅くなる可能性がある。submodules: 特定のジョブで必要でない場合、サブモジュールのチェックアウトを避ける。サブモジュールの取得は大きなオーバーヘッドを追加する。lfs: Git LFS(Large File Storage)ファイルを効率的に管理。必要でない場合、lfs: falseに設定。- 部分クローン: 非常に大きなリポジトリの場合、Git の部分クローン機能(
--filter=blob:noneや--filter=tree:0)の使用を検討、ただしこれは通常専用のアクションや Git クライアント設定で処理される。
- Copilot へのガイダンス:
- 時間と帯域幅を大幅に節約するため、ほとんどのビルドとテストジョブでデフォルトとして
actions/checkout@v4をfetch-depth: 1で使用。 - ワークフローが完全な Git 履歴を明示的に必要とする場合(例:リリースタグ付け、深いコミット解析、
git blame操作)のみfetch-depth: 0を使用。 - ワークフローの目的に厳密に必要でない場合、サブモジュールのチェックアウト(
submodules: false)に対して助言。 - 大きなバイナリファイルがリポジトリに存在する場合、LFS 使用の最適化を提案。
- 時間と帯域幅を大幅に節約するため、ほとんどのビルドとテストジョブでデフォルトとして
5. ジョブ間・ワークフロー間通信のためのアーティファクト
- 原則: 同一ワークフロー内のジョブ間や異なるワークフロー間でデータを渡すため、ビルド出力(アーティファクト)を効率的に保存・取得し、データの永続性と整合性を確保する。
- 詳細な説明:
actions/upload-artifact: ジョブによって生成されたファイルやディレクトリをアップロードするために使用。アーティファクトは自動的に圧縮され、後でダウンロード可能。actions/download-artifact: 後続のジョブやワークフローでアーティファクトをダウンロードするために使用。すべてのアーティファクトまたは名前による特定のものをダウンロード可能。retention-days: ストレージコストとコンプライアンスの管理に重要。アーティファクトの重要性と規制要件に基づいて適切な保持期間を設定。- 使用例: ビルド出力(実行可能ファイル、コンパイルされたコード、Docker イメージ)、テストレポート(JUnit XML、HTML レポート)、コードカバレッジレポート、セキュリティスキャン結果、生成されたドキュメント、静的ウェブサイトビルド。
- 制限事項: アーティファクトはアップロード後は不変。アーティファクトあたりの最大サイズは数ギガバイト可能だが、ストレージコストに注意。
- Copilot へのガイダンス:
- 同一ワークフロー内や異なるワークフロー間で大きなファイルを信頼性を持って渡すために
actions/upload-artifact@v3とactions/download-artifact@v3を使用し、モジュラリティと効率性を促進。 - ストレージコストを管理し、古いアーティファクトが削除されるように、アーティファクトに適切な
retention-daysを設定。 - 簡単なアクセス、履歴分析、外部レポートツールとの統合のため、テストレポート、カバレッジレポート、セキュリティスキャン結果をアーティファクトとしてアップロードすることを助言。
- ビルドジョブからデプロイメントジョブへコンパイル済みバイナリやパッケージ化されたアプリケーションを渡すためのアーティファクト使用を提案し、ビルド・テストされた正確に同じアーティファクトがデプロイされることを確保。
- 同一ワークフロー内や異なるワークフロー間で大きなファイルを信頼性を持って渡すために
CI/CD での包括的テスト(拡張版)
1. 単体テスト
- 原則: 個別のコード要素(関数、クラス、モジュール)が独立して正しく機能することを保証するため、すべてのコードプッシュで単体テストを実行。これらは最も高速で数の多いテスト。
- 詳細な説明:
- 高速フィードバック: 単体テストは迅速に実行され、開発者にコード品質と正確性に関する即座のフィードバックを提供すべき。単体テストの並列化が強く推奨される。
- コードカバレッジ: コードカバレッジツール(JS の Istanbul、Python の Coverage.py、Java の JaCoCo)を統合し、最小カバレッジ閾値を強制。高いカバレッジを目指すが、単なる行カバレッジではなく意味のあるテストに焦点を当てる。
- テストレポート:
actions/upload-artifact(例:JUnit XML レポート)や、GitHub Checks/Annotations と統合する専用のテストレポーターアクションを使用してテスト結果を公開。 - モッキングとスタブ: テスト対象のユニットを依存関係から分離するため、モックやスタブの使用を強調。
- Copilot へのガイダンス:
- CI パイプラインの早期で単体テストを実行する専用ジョブを設定し、理想的にはすべての
pushとpull_requestでトリガー。 - 適切な言語固有のテストランナーとフレームワーク(Jest、Vitest、Pytest、Go testing、JUnit、NUnit、XUnit、RSpec)を使用。
- コードカバレッジレポートの収集・公開と、傾向分析のための Codecov、Coveralls、SonarQube などのサービスとの統合を推奨。
- 実行時間を短縮するための単体テスト並列化戦略を提案。
- CI パイプラインの早期で単体テストを実行する専用ジョブを設定し、理想的にはすべての
2. 統合テスト
- 原則: 異なるコンポーネントやサービス間の相互作用を検証し、それらが期待通りに連携することを確認するため統合テストを実行。これらのテストは通常、実際の依存関係(例:データベース、API)を含む。
- 詳細な説明:
- サービスプロビジョニング: 一貫した分離されたテスト環境を提供するため、ジョブ内で
servicesを使用して Docker コンテナ経由で一時的なデータベース、メッセージキュー、外部 API、その他の依存関係を立ち上げる。 - テストダブル vs リアルサービス: 純粋な単体テストのための外部サービスのモッキングと、より現実的な統合テストのための軽量な実際のインスタンス使用とのバランスを取る。実際の統合ポイントをテストする場合は実際のインスタンスを優先。
- テストデータ管理: テストデータの管理を計画し、テストが反復可能で、実行間でデータがクリーンアップまたはリセットされることを確保。
- 実行時間: 統合テストは通常単体テストより遅い。実行を最適化し、単体テストほど頻繁でない実行を検討(例:すべてのプッシュではなく PR マージ時)。
- サービスプロビジョニング: 一貫した分離されたテスト環境を提供するため、ジョブ内で
- Copilot へのガイダンス:
- ワークフロー定義での
services使用やテスト中の Docker Compose 使用により、必要なサービス(PostgreSQL/MySQL などのデータベース、RabbitMQ/Kafka などのメッセージキュー、Redis などのインメモリキャッシュ)をプロビジョン。 - 統合の問題を早期に捕捉するため、単体テスト後、E2E テスト前に統合テストを実行することを助言。
- GitHub Actions ワークフローでの
serviceコンテナの設定方法の例を提供。 - 統合テスト実行のためのテストデータの作成とクリーンアップ戦略を提案。
- ワークフロー定義での
3. エンドツーエンド(E2E)テスト
- 原則: UI からバックエンドまでの完全なアプリケーションフローを検証し、ユーザーの視点からシステム全体が意図通りに動作することを確保するため、完全なユーザー行動をシミュレート。
- 詳細な説明:
- ツール: Cypress、Playwright、Selenium などの現代的な E2E テストフレームワークを使用。これらはブラウザ自動化機能を提供。
- ステージング環境: 最大の忠実度のため、本番に近いデプロイ済みステージング環境で E2E テストを実行することが理想的。専用で分離されたリソースがない限り、CI 内で直接実行は避ける。
- 不安定性の軽減: 明示的な待機、堅牢なセレクター、失敗テストの再試行、注意深いテストデータ管理により不安定性に事前対処。不安定なテストはパイプラインへの信頼を損なう。
- ビジュアル回帰テスト: UI の不一致を捕捉するためのビジュアル回帰テスト(例:Applitools、Percy)の統合を検討。
- レポート: デバッグ支援のため失敗時にスクリーンショットとビデオ録画をキャプチャ。
- Copilot へのガイダンス:
- E2E テスト用の Cypress、Playwright、Selenium などのツールを使用し、GitHub Actions 内での設定ガイダンスを提供。
- 本番前の問題を捕捉し、完全なデプロイメントプロセスを検証するため、デプロイ済みステージング環境での E2E テスト実行を推奨。
- デバッグ支援とテスト結果のより豊富なコンテキスト提供のため、テストレポート、失敗時のビデオ録画、スクリーンショットを設定。
- 堅牢な要素選択や再試行メカニズムなど、E2E テストの不安定性を最小化する戦略を助言。
4. パフォーマンス・負荷テスト
- 原則: ボトルネックを特定し、スケーラビリティを確保し、回帰を防ぐため、予想されるピーク負荷条件下でのアプリケーションのパフォーマンスと動作を評価。
- 詳細な説明:
- ツール: JMeter、k6、Locust、Gatling、Artillery。言語、複雑さ、特定のニーズに基づいて選択。
- 統合: 継続的なパフォーマンス回帰検出のため CI へ統合。単体/統合テストより頻度低く実行(例:夜間、週次、または重要な機能マージ時)。
- 閾値: 明確なパフォーマンス閾値(例:応答時間、スループット、エラー率)を定義し、これらを超えた場合はビルド失敗。
- ベースライン比較: 劣化を検出するため、確立されたベースラインと現在のパフォーマンス指標を比較。
- Copilot へのガイダンス:
- 重要なアプリケーションの CI パイプラインへのパフォーマンス・負荷テスト統合を提案し、一般的なツールの例を提供。
- パフォーマンスベースラインの設定と、設定した閾値を超えてパフォーマンスが劣化した場合のビルド失敗を助言。
- 本番負荷パターンをシミュレートする専用環境でのこれらのテスト実行を推奨。
- 最適化領域を特定するためのパフォーマンステスト結果分析(例:データベースクエリ、API エンドポイント)をガイド。
5. テストレポートと可視性
- 原則: 透明性を促進し、迅速な問題解決を可能にするため、すべてのステークホルダー(開発者、QA、プロダクトオーナー)にテスト結果を簡単にアクセス可能、理解可能、可視化する。
- 詳細な説明:
- GitHub Checks/Annotations: プルリクエスト内で直接インラインフィードバックを活用し、どのテストが合格/失敗したかを示し、詳細レポートへのリンクを提供。
- アーティファクト: 長期保存と詳細検査のため、包括的なテストレポート(JUnit XML、HTML レポート、コードカバレッジレポート、ビデオ録画、スクリーンショット)をアーティファクトとしてアップロード。
- ダッシュボード統合: 集約されたビューと履歴傾向のため、外部ダッシュボードやレポートツール(例:SonarQube、カスタムレポートツール、Allure Report、TestRail)に結果をプッシュ。
- ステータスバッジ: 一目で最新のビルド/テストステータスを示すため、README で GitHub Actions ステータスバッジを使用。
- Copilot へのガイダンス:
- GitHub UI 内で直接即座のフィードバックと簡単なデバッグのため、PR 上にテスト結果をアノテーションまたはチェックとして公開するアクションを使用。
- 後の検査と履歴分析のため、エラースクリーンショットなどのネガティブ結果を含む詳細なテストレポート(例:XML、HTML、JSON)をアーティファクトとしてアップロード。
- テスト実行傾向と品質指標のより包括的な視点のため、外部レポートツールとの統合を助言。
- CI/CD 健全性の迅速な可視性のため、README へのワークフローステータスバッジ追加を提案。
高度なデプロイメント戦略(拡張版)
1. ステージング環境デプロイメント
- 原則: 包括的な検証、ユーザー受入テスト(UAT)、本番昇格前の最終チェックのため、本番を密接に模倣するステージング環境へデプロイ。
- 詳細な説明:
- 本番のミラーリング: ステージングはインフラストラクチャ、データ、設定、セキュリティの観点で本番を密接に模倣すべき。重要な相違は本番での問題につながる可能性。
- 自動昇格: 成功した UAT と必要な手動承認後の、ステージングから本番への自動昇格を実装。これにより人的エラーを削減し、リリースを高速化。
- 環境保護: GitHub Actions の環境保護ルールを使用して偶発的なデプロイメントを防ぎ、手動承認を強制し、ステージングへデプロイ可能なブランチを制限。
- データリフレッシュ: 現実的なテストシナリオを確保するため、ステージングデータを本番から定期的にリフレッシュ(必要に応じて匿名化)。
- Copilot へのガイダンス:
- 承認ルール、シークレット保護、適切なブランチ保護ポリシーを持つステージング専用の
environmentを作成。 - 特定の開発またはリリースブランチ(例:
develop、release/*)への成功マージ時にステージングへ自動デプロイするワークフローを設計。 - テストの忠実度を最大化するため、ステージング環境が可能な限り本番に近いことを確保することを助言。
- ステージング上での自動スモークテストとデプロイ後検証の実装を提案。
- 承認ルール、シークレット保護、適切なブランチ保護ポリシーを持つステージング専用の
2. 本番環境デプロイメント
- 原則: 徹底的な検証、潜在的に複数層の手動承認、堅牢な自動チェック後にのみ本番へデプロイし、安定性とゼロダウンタイムを優先。
- 詳細な説明:
- 手動承認: 本番デプロイメントには重要で、多くの場合複数のチームメンバー、セキュリティ承認、変更管理プロセスが関与。GitHub Environments がこれをネイティブサポート。
- ロールバック機能: 予期しない問題からの迅速な回復には必須。前の安定状態に戻す迅速で信頼性の高い方法を確保。
- デプロイメント中の可観測性: 異常やパフォーマンス劣化について、デプロイメント中および直後に本番を密接に監視。ダッシュボード、アラート、トレーシングを使用。
- プログレッシブデリバリー: より安全なロールアウトのため、blue/green、カナリー、ダークローンチなどの高度な技術を検討。
- 緊急デプロイメント: セキュリティチェックは維持しながら、非必須承認をバイパスする重要なホットフィックス用の別の、高度に迅速化されたパイプラインを用意。
- Copilot へのガイダンス:
- 必要なレビュアー、厳格なブランチ保護、明確なデプロイメントウィンドウを持つ本番専用の
environmentを作成。 - 外部 ITSM や変更管理システムとの統合を潜在的に含む、本番デプロイメント用の手動承認ステップを実装。
- 明確で十分にテストされたロールバック戦略と、デプロイメント失敗時の自動ロールバック手順の重要性を強調。
- デプロイメント後即座に問題を検出・対応するため、本番システムの包括的な監視とアラートの設定を助言。
- 必要なレビュアー、厳格なブランチ保護、明確なデプロイメントウィンドウを持つ本番専用の
3. デプロイメントタイプ(基本的なローリング更新を超えて)
- ローリング更新(デプロイメントのデフォルト): 古いバージョンのインスタンスを新しいものに段階的に置換。ほとんどの場合、特にステートレスアプリケーションに適している。
- ガイダンス: ロールアウト速度と可用性の細かい制御のため、
maxSurge(望ましいレプリカ数を超えて作成可能な新しいインスタンス数)とmaxUnavailable(使用不可になり得る古いインスタンス数)を設定。
- ガイダンス: ロールアウト速度と可用性の細かい制御のため、
- Blue/Green デプロイメント: 別の環境で既存の安定バージョン(blue)と並行して新しいバージョン(green)をデプロイし、その後トラフィックを blue から green に完全に切り替え。
- ガイダンス: ゼロダウンタイムリリースと簡単なロールバックを必要とする重要なアプリケーションに提案。2 つの同一環境とトラフィックルーター(ロードバランサー、Ingress コントローラー、DNS)の管理が必要。
- 利点: blue 環境へトラフィックを戻すことによる瞬時のロールバック。
- カナリーデプロイメント: 完全なロールアウト前に、少数のユーザー(例:5-10%)に新しいバージョンを段階的にロールアウト。カナリーグループのパフォーマンスとエラー率を監視。
- ガイダンス: 制御された影響範囲での新機能や変更のテストに推奨。トラフィック分割と指標ベース分析をサポートする Service Mesh(Istio、Linkerd)または Ingress コントローラーで実装。
- 利点: 最小のユーザー影響での問題の早期発見。
- ダークローンチ/フィーチャーフラグ: 新しいコードをデプロイするが、フィーチャーフラグ経由で特定のユーザー/グループに対して切り替えられるまで、ユーザーから機能を隠しておく。
- ガイダンス: デプロイメントとリリースを分離し、新機能の継続的露出なしに継続的デリバリーを可能にするため助言。フィーチャーフラグ管理システム(LaunchDarkly、Split.io、Unleash)を使用。
- 利点: デプロイメントリスクの削減、A/B テストの実現、段階的ロールアウトの許可。
- A/B テストデプロイメント: ユーザー行動とビジネス指標に基づいてパフォーマンスを比較するため、異なるユーザーセグメントに機能の複数バージョンを同時にデプロイ。
- ガイダンス: 専用の A/B テストプラットフォームとの統合や、フィーチャーフラグと分析を使用したカスタムロジックの構築を提案。
4. ロールバック戦略とインシデント対応
- 原則: 問題が発生した場合にダウンタイムとビジネス影響を最小化して、前の安定バージョンに迅速かつ安全に戻ることができる。これには事前計画が必要。
- 詳細な説明:
- 自動ロールバック: 監視アラート(例:エラーの急激な増加、高レイテンシー)やデプロイ後ヘルスチェックの失敗に基づいてロールバックを自動的にトリガーするメカニズムを実装。
- バージョン管理されたアーティファクト: 高速回復のため、前の成功したビルドアーティファクト、Docker イメージ、インフラストラクチャ状態が容易に利用可能で簡単にデプロイ可能であることを確保。
- ランブック: 自動化では不十分な場合や複雑なシナリオでの手動介入のため、明確で簡潔で実行可能なロールバック手順を文書化。これらは定期的にレビューとテストを実施。
- インシデント後レビュー: 失敗の根本原因を理解し、学んだ教訓を特定し、回復力を向上させ MTTR を削減する予防措置を実装するため、無責任なインシデント後レビュー(PIR)を実施。
- コミュニケーション計画: インシデントとロールバック中のステークホルダー向けの明確なコミュニケーション計画を用意。
- Copilot へのガイダンス:
- 高速回復のため、前の成功したビルドアーティファクトとイメージを保存し、それらがバージョン管理され簡単に取得可能であることをユーザーに指示。
- 監視やヘルスチェック失敗によってトリガーされるパイプライン内の自動ロールバックステップの実装を助言し、例を提供。
- 変更が容易に可逆的であることを意味する、「元に戻す」ことを念頭に置いたアプリケーション構築を強調。
- 一般的なインシデントシナリオ用の包括的なランブックの作成(段階的なロールバック指示を含む)を提案し、MTTR での重要性をハイライト。
- 自動または手動ロールバックをトリガーするのに十分な特定性と実用性を持つアラートの設定をガイド。
GitHub Actions ワークフロー レビューチェックリスト(包括的)
このチェックリストは、GitHub Actions ワークフローがセキュリティ、パフォーマンス、信頼性のベストプラクティスに従っていることを確認するため、細かい基準セットを提供します。
-
一般的な構造と設計:
- ワークフローの
nameは明確で説明的かつ一意か? onトリガーはワークフローの目的に適切か(例:push、pull_request、workflow_dispatch、schedule)?パス/ブランチフィルターは効果的に使用されているか?- 重要なワークフローや共有リソースで競合状態やリソース枯渇を防ぐため
concurrencyが使用されているか? - グローバル
permissionsが最小権限の原則(デフォルトでcontents: read)に設定され、ジョブ用の特定のオーバーライドがあるか? - 重複を削減し保守性を向上させるため、一般的なパターンに再利用可能なワークフロー(
workflow_call)が活用されているか? - ワークフローは意味のあるジョブとステップ名で論理的に整理されているか?
- ワークフローの
-
ジョブとステップのベストプラクティス:
- ジョブは明確に命名され、明確なフェーズ(例:
build、lint、test、deploy)を表しているか? - 適切な実行順序を確保するため、ジョブ間で
needs依存関係が正しく定義されているか? - ジョブ間・ワークフロー間通信に
outputsが効率的に使用されているか? - 条件付きジョブ/ステップ実行に
if条件が効果的に使用されているか(例:環境固有デプロイメント、ブランチ固有アクション)? - すべての
usesアクションは安全にバージョン管理されているか(完全なコミット SHA または@v4などの特定のメジャーバージョンタグに固定)?mainやlatestタグは避けているか? runコマンドは効率的でクリーンか(&&で結合、一時ファイル削除、複数行スクリプトの明確な書式)?- 環境変数(
env)は適切なスコープ(ワークフロー、ジョブ、ステップ)で定義され、機密データがハードコードされていないか? - 停止したワークフローを防ぐため、長時間実行ジョブに
timeout-minutesが設定されているか?
- ジョブは明確に命名され、明確なフェーズ(例:
-
セキュリティの考慮事項:
- すべての機密データが GitHub
secretsコンテキスト(${{ secrets.MY_SECRET }})からのみアクセスされているか?ハードコードされておらず、マスクされていてもログに露出していないか? - 可能な場合、長期間の認証情報を排除するため、クラウド認証に OpenID Connect(OIDC)が使用されているか?
GITHUB_TOKEN権限スコープが明示的に定義され、必要最小限のアクセス(ベースラインとしてcontents: read)に制限されているか?- 脆弱な依存関係をスキャンするため、Software Composition Analysis(SCA)ツール(例:
dependency-review-action、Snyk)が統合されているか? - ソースコードの脆弱性をスキャンし、重要な発見でビルドをブロックする Static Application Security Testing(SAST)ツール(例:CodeQL、SonarQube)が統合されているか?
- リポジトリでシークレットスキャンが有効化され、ローカルでの認証情報漏洩防止のためプリコミットフックが提案されているか?
- コンテナイメージが使用される場合、コンテナイメージ署名(例:Notary、Cosign)とデプロイメントワークフローでの検証の戦略があるか?
- セルフホストランナーでは、セキュリティ堅牢化ガイドラインに従い、ネットワークアクセスが制限されているか?
- すべての機密データが GitHub
-
最適化とパフォーマンス:
- パッケージマネージャの依存関係(
node_modules、pipキャッシュ、Maven/Gradle キャッシュ)とビルド出力に対してキャッシュ(actions/cache)が効果的に使用されているか? - 最適なキャッシュヒット率のため、キャッシュ
keyとrestore-keysが設計されているか(例:hashFiles使用)? - 異なる環境、言語バージョン、OS でのテストやビルドの並列化に
strategy.matrixが使用されているか? - 完全な Git 履歴が不要な場合、
actions/checkoutでfetch-depth: 1が使用されているか? - 再構築や再取得ではなく、ジョブ/ワークフロー間でのデータ転送にアーティファクト(
actions/upload-artifact、actions/download-artifact)が効率的に使用されているか? - 大きなファイルが Git LFS で管理され、必要に応じてチェックアウトが最適化されているか?
- パッケージマネージャの依存関係(
-
テスト戦略統合:
- パイプライン早期で専用ジョブを持つ包括的な単体テストが設定されているか?
- 理想的に依存関係に
servicesを活用し、単体テスト後に実行される統合テストが定義されているか? - エンドツーエンド(E2E)テストが含まれ、できればステージング環境に対して、堅牢な不安定性軽減が実装されているか?
- 定義された閾値を持つ重要なアプリケーション向けパフォーマンス・負荷テストが統合されているか?
- すべてのテストレポート(JUnit XML、HTML、カバレッジ)が収集され、アーティファクトとして公開され、明確な可視性のため GitHub Checks/Annotations に統合されているか?
- コードカバレッジが追跡され、最小閾値で強制されているか?
-
デプロイメント戦略と信頼性:
- ステージングと本番デプロイメントが適切な保護(手動承認、必要なレビュアー、ブランチ制限)を持つ GitHub
environmentルールを使用しているか? - 機密な本番デプロイメント用に手動承認ステップが設定されているか?
- 明確で十分にテストされたロールバック戦略が整備され、可能な場合は自動化されているか(例:
kubectl rollout undo、前の安定イメージへの復帰)? - 選択されたデプロイメントタイプ(例:ローリング、blue/green、カナリー、ダークローンチ)がアプリケーションの重要度とリスク許容度に適しているか?
- 成功したデプロイメントを検証するため、デプロイ後ヘルスチェックと自動スモークテストが実装されているか?
- ワークフローが一時的な失敗に対して弾力性があるか(例:不安定なネットワーク操作の再試行)?
- ステージングと本番デプロイメントが適切な保護(手動承認、必要なレビュアー、ブランチ制限)を持つ GitHub
-
可観測性と監視:
- ワークフロー失敗のデバッグに十分なログ記録があるか(アプリケーションログに STDOUT/STDERR を使用)?
- 関連するアプリケーションとインフラストラクチャ指標が収集・露出されているか(例:Prometheus 指標)?
- 重要なワークフロー失敗、デプロイメント問題、本番で検出されたアプリケーション異常に対してアラートが設定されているか?
- マイクロサービスアーキテクチャでリクエストフローを理解するため、分散トレーシング(例:OpenTelemetry、Jaeger)が統合されているか?
- ストレージとコンプライアンスを管理するため、アーティファクトの
retention-daysが適切に設定されているか?
一般的な GitHub Actions 問題のトラブルシューティング(詳細)
この章は、GitHub Actions ワークフローで遭遇する頻繁な問題を診断・解決するための拡張ガイドを提供します。
1. ワークフローがトリガーされない、またはジョブ/ステップが予期せずスキップされる
- 根本原因:
onトリガーの不一致、不正確なpathsやbranchesフィルター、誤ったif条件、またはconcurrency制限。 - 実行可能な手順:
- トリガーの確認:
- ワークフローをトリガーすべきイベントと正確に一致するため
onブロックをチェック(例:push、pull_request、workflow_dispatch、schedule)。 pathsやbranchesフィルターが期待するファイルやブランチと一致することを確認。workflow_dispatch使用時は、ワークフローファイルがデフォルトブランチにあり、手動トリガー時に必要なinputsが正しく提供されていることを確認。
- ワークフローをトリガーすべきイベントと正確に一致するため
if条件の検査:- 条件ロジックが期待するシナリオで真と評価されることを確認(例:
github.ref == 'refs/heads/main'、github.event_name == 'push')。 - 式構文が正しく、変数名が有効であることを確認。
- 異なるイベントタイプ間で利用可能なコンテキスト変数の違いを理解(例:
github.head_refはプルリクエストでのみ利用可能)。
- 条件ロジックが期待するシナリオで真と評価されることを確認(例:
- 並行性制限: 並行性グループが他の実行をブロックしていないか確認。必要に応じて
cancel-in-progressを調整。 - ブランチ保護ルール: 特定のブランチでワークフローが実行されることを防いでいたり、通過していない特定のチェックを要求するブランチ保護ルールがないことを確保。
- トリガーの確認:
2. 権限エラー(Resource not accessible by integration、Permission denied)
- 根本原因:
GITHUB_TOKENに必要な権限がない、環境シークレットアクセスが不正、または外部アクション用の権限が不十分。 - 実行可能な手順:
GITHUB_TOKEN権限:- ワークフローまたはジョブレベルで
permissionsを明示的に設定し、必要なアクセスを許可。 - リポジトリの変更には
contents: write、プルリクエストの更新にはpull-requests: writeが必要。 - 組織レベルの設定がデフォルト
GITHUB_TOKEN権限を制限していないことを確認。
- ワークフローまたはジョブレベルで
- 環境シークレット: 適切な環境にデプロイしており、必要な承認を受けていることを確認。
- 外部統合: サードパーティサービス(AWS、Azure、GCP)について、認証情報が有効で必要な権限があることを確認。
3. キャッシュ問題(Cache not found、Cache miss、Cache creation failed)
- 根本原因: 不正なキャッシュキーロジック、
path不一致、キャッシュサイズ制限、または頻繁なキャッシュ無効化。 - 実行可能な手順:
- キャッシュキーの検証:
- キャッシュキーが正しく
hashFilesを使用してファイルの変更でのみ無効化されることを確認。 pathパラメータが実際にキャッシュしたいディレクトリ/ファイルと一致することを確認。- 複数パスの場合、すべてが存在し、アクセス可能であることを確認。
restore-keysの順序と効果を確認し、部分的な一致が期待通りに動作することを確保。
- キャッシュキーが正しく
- キャッシュサイズと制限: リポジトリごとの GitHub Actions キャッシュサイズ制限を認識。キャッシュが非常に大きい場合、頻繁に削除される可能性。
- ブランチスコープ: キャッシュがブランチスコープであることを理解し、クロスブランチ共有戦略を検討。
- キャッシュキーの検証:
4. 長時間実行ワークフローまたはタイムアウト
- 根本原因: 非効率なステップ、並列性の欠如、大きな依存関係、最適化されていない Docker イメージビルド、またはランナーでのリソースボトルネック。
- 実行可能な手順:
- 実行時間のプロファイル:
- ワークフローログを分析してボトルネックを特定(最も時間のかかるステップ)。
- 並列実行可能なジョブを特定し、
needs依存関係を最適化。 - 依存関係インストール、テスト実行、ビルドプロセスの持続時間をレビュー。
- キャッシュ最適化: 依存関係やビルドアーティファクトの効果的なキャッシュを実装。
- マトリックス並列化: 複数の設定でテストを並列実行するためマトリックス戦略を使用。
- ランナーのアップグレード: より高いパフォーマンスが必要な場合はセルフホストランナーまたはより大きな GitHub ホストランナーを検討。
- 実行時間のプロファイル:
5. CI での不安定テスト(Random failures、Passes locally, fails in CI)
- 根本原因: 非決定論的テスト、競合状態、ローカルと CI 間の環境の不整合、外部サービスへの依存、またはテスト分離の不備。
- 実行可能な手順:
- テスト分離の確保:
- 各テストが独立しており、他のテストの状態に依存しないことを確認。
- テスト間でデータベース、ファイル、グローバル状態をクリーンアップ。
- 競合状態の修正: 非同期操作に適切な待機とタイムアウトを使用。
- 環境の一致: 依存関係バージョン、環境変数、システム設定がローカルと一致することを確保。
- 外部依存関係の処理: 外部サービスをモックするか、テスト用の安定したテスト環境を使用。
- テスト分離の確保:
6. デプロイメント失敗(デプロイ後にアプリケーションが動作しない)
- 根本原因: 設定ドリフト、環境の違い、ランタイム依存関係の欠如、アプリケーションエラー、またはデプロイ後のネットワーク問題。
- 実行可能な手順:
- 徹底的なログレビュー:
- アプリケーション、サーバー、コンテナログでエラーメッセージ、スタックトレース、警告を確認。
- デプロイメントログでプロセス中の失敗やエラーを確認。
- 設定検証: 環境変数、シークレット、設定ファイルが正しく設定され、アクセス可能であることを確認。
- 依存関係チェック: すべてのランタイム依存関係、データベース接続、外部サービスが利用可能で接続可能であることを確認。
- ヘルスチェック: ロードバランサーやオーケストレーションツールがアプリケーションをヘルシーとして認識していることを確認。
- 徹底的なログレビュー:
結論
GitHub Actions は、ソフトウェア開発ライフサイクルを自動化するための強力で柔軟なプラットフォームです。シークレットとトークン権限の保護から、キャッシュと並列化によるパフォーマンス最適化、包括的なテストと堅牢なデプロイメント戦略の実装まで、これらのベストプラクティスを厳密に適用することで、開発者は高効率で安全、信頼性の高い CI/CD パイプラインの構築を指導できます。CI/CD は反復的な旅であることを覚えておいてください。より高速で安全、自信を持ったリリースを達成するため、パイプラインを継続的に測定、最適化、保護してください。あなたの詳細なガイダンスは、チームが GitHub Actions をその最大限の可能性まで活用し、自信を持って高品質なソフトウェアを提供することを可能にします。この広範囲にわたる文書は、GitHub Actions を使用した CI/CD をマスターしようとする人にとって基本的なリソースとして機能します。