CI/CDツールの選択肢は数多くありますが、GitHub Actionsはリポジトリとの一体化という圧倒的な利便性により、急速に普及しました。Jenkins、CircleCI、GitLab CIといった既存ツールから移行するチームも増えています。
筆者が特に評価するのは、ワークフローの定義がリポジトリ内に完結する点です。インフラの変更履歴がコードと同じリポジトリで管理され、プルリクエストベースでレビューできるため、CI/CD設定の品質管理が格段に向上します。本記事では、実際のプロジェクトで培ったワークフロー設計のベストプラクティスを共有します。
効率的なCI/CDパイプラインを構築するには、まず設計原則を明確にすることが重要です。
開発者がプッシュしてから結果がわかるまでの時間が、開発体験を大きく左右します。筆者のチームでは「プルリクエストのチェックは5分以内」を目標にしています。これを実現するために、ジョブの並列化とキャッシュ戦略が鍵となります。
name: CI Pipeline
on:
pull_request:
branches: [main, develop]
push:
branches: [main]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npm run lint
test:
runs-on: ubuntu-latest
strategy:
matrix:
shard: [1, 2, 3, 4]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npm run test -- --shard=${{ matrix.shard }}/4
build:
needs: [lint, test]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npm run build
- uses: actions/upload-artifact@v4
with:
name: build-output
path: dist/
この例では、lintとtestを並列実行し、両方が成功した後にbuildを実行しています。テストは4つのシャードに分割して並列実行することで、実行時間を大幅に短縮しています。
ビルド時間を短縮する最も効果的な方法の一つがキャッシュ戦略です。GitHub Actionsでは複数のキャッシュ手法が利用できます。
- uses: actions/cache@v4
with:
path: |
~/.npm
node_modules
key: deps-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
deps-${{ runner.os }}-
Dockerイメージのビルドを含むパイプラインでは、レイヤーキャッシュが重要です。
- uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
cache-from: type=gha
cache-to: type=gha,mode=max
type=ghaを指定することで、GitHub Actionsのキャッシュバックエンドを利用したDockerレイヤーキャッシュが実現できます。筆者の環境では、これによりDockerビルドが平均8分から2分に短縮されました。
本番運用を見据えたデプロイメントワークフローでは、環境ごとの分離と承認フローが不可欠です。
deploy-staging:
needs: build
runs-on: ubuntu-latest
environment: staging
steps:
- uses: actions/download-artifact@v4
with:
name: build-output
path: dist/
- name: Deploy to staging
run: |
aws s3 sync dist/ s3://${{ vars.S3_BUCKET_STAGING }}/ --delete
aws cloudfront create-invalidation \
--distribution-id ${{ vars.CF_DIST_STAGING }} \
--paths "/*"
deploy-production:
needs: deploy-staging
runs-on: ubuntu-latest
environment:
name: production
url: https://example.com
steps:
- uses: actions/download-artifact@v4
with:
name: build-output
path: dist/
- name: Deploy to production
run: |
aws s3 sync dist/ s3://${{ vars.S3_BUCKET_PROD }}/ --delete
aws cloudfront create-invalidation \
--distribution-id ${{ vars.CF_DIST_PROD }} \
--paths "/*"
GitHubのEnvironments機能を活用すると、productionデプロイメントに必須レビュワーの承認を設定できます。これにより、コードレビュー済みの変更のみが本番環境に適用されることをワークフローレベルで保証できます。
CI/CDパイプラインにおけるシークレット管理は極めて重要です。GitHub Actionsでは、Organization、Repository、Environmentの3レベルでシークレットを管理できます。
長期的なアクセスキーをシークレットに保存するのではなく、OIDCプロバイダー連携を使用することを強く推奨します。
- uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789012:role/github-actions-deploy
aws-region: ap-northeast-1
この方式では、ワークフロー実行時にのみ一時的な認証情報が発行されるため、シークレットの漏洩リスクを大幅に低減できます。
組織内で複数のリポジトリを管理している場合、共通のワークフローを再利用可能な形で設計することが運用効率を大きく向上させます。
# .github/workflows/reusable-deploy.yml
name: Reusable Deploy
on:
workflow_call:
inputs:
environment:
required: true
type: string
artifact-name:
required: true
type: string
secrets:
AWS_ROLE_ARN:
required: true
jobs:
deploy:
runs-on: ubuntu-latest
environment: ${{ inputs.environment }}
steps:
- uses: actions/download-artifact@v4
with:
name: ${{ inputs.artifact-name }}
- uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
aws-region: ap-northeast-1
- run: echo "Deploying to ${{ inputs.environment }}"
再利用可能なワークフローは、workflow_callトリガーで定義します。これにより、デプロイ手順の標準化と、変更時の影響範囲の一元管理が可能になります。
GitHub ActionsによるCI/CDパイプラインは、適切に設計すれば開発チームの生産性を劇的に向上させます。ジョブの並列化によるフィードバック高速化、キャッシュ戦略によるビルド時間短縮、Environment機能による安全なデプロイフロー、そしてOIDC連携によるセキュアな認証は、いずれも本番運用で必須の要素です。ワークフローファイルもコードの一部として品質を管理し、継続的に改善していく文化を根付かせることが、長期的な成功の鍵です。