← ブログ一覧

GitHub Actions による CI/CD パイプライン構築実践ガイド

自動テスト・ビルド・デプロイを GitHub Actions で実装する手順を解説。ワークフロー設計・環境変数管理・マトリクステスト・本番デプロイまで、受託開発で即使える実践ガイド。

#CI/CD#DevOps#GitHub#テスト
GitHub Actions による CI/CD パイプライン構築実践ガイド

GitHub Actions による CI/CD パイプライン構築実践ガイド

受託開発・自社開発の現場では、コードの品質を保ちながら素早くリリースするために CI/CD パイプラインが不可欠です。GitHub Actions は GitHub に統合されており、追加のサービス契約なしで自動テスト・ビルド・デプロイを実現できます。

本記事では、実務で即使える GitHub Actions の実装パターンを、ワークフロー設計から本番デプロイまで具体例とともに解説します。


1. GitHub Actions の基本構成と設計方針

ワークフローファイルの配置

GitHub Actions は .github/workflows/ ディレクトリ配下の YAML ファイルで定義します。実務では用途別に複数ファイルに分割すると管理しやすくなります。

.github/
└── workflows/
    ├── ci.yml          # プルリクエスト時の自動テスト
    ├── deploy-stg.yml  # ステージング環境へのデプロイ
    └── deploy-prod.yml # 本番環境へのデプロイ

設計の基本方針

| 観点 | 推奨アプローチ | 理由 | |------|--------------|------| | トリガー | PR 時は軽量テスト、main マージ時は完全テスト | フィードバック速度とコスト削減 | | ジョブ分割 | テスト・ビルド・デプロイを別ジョブに | 失敗箇所の特定が容易 | | 環境変数 | Repository Secrets で管理 | 認証情報の Git 管理を回避 | | キャッシュ | 依存パッケージをキャッシュ | ビルド時間を 30〜50% 短縮 | | 並列実行 | Matrix Strategy で複数環境テスト | Node.js 複数バージョン対応など |


2. プルリクエスト時の自動テストワークフロー

基本的な CI ワークフロー

TypeScript + Next.js プロジェクトでの典型例です。

# .github/workflows/ci.yml
name: CI

on:
  pull_request:
    branches: [main, develop]

jobs:
  test:
    runs-on: ubuntu-latest
    
    strategy:
      matrix:
        node-version: [18.x, 20.x]
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Setup Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
          cache: 'npm'
      
      - name: Install dependencies
        run: npm ci
      
      - name: Lint
        run: npm run lint
      
      - name: Type check
        run: npm run type-check
      
      - name: Unit tests
        run: npm run test:unit
      
      - name: Build
        run: npm run build
        env:
          NODE_ENV: production

実装のポイント

  • npm ci を使う: npm install より高速で、package-lock.json と厳密に一致
  • Matrix Strategy: 複数の Node.js バージョンで並列テスト
  • cache: 'npm': node_modules のキャッシュで 2 回目以降が高速化
  • 段階的チェック: Lint → 型チェック → テスト → ビルド の順で早期に失敗させる

3. 環境変数とシークレット管理

Repository Secrets の設定

GitHub リポジトリの Settings > Secrets and variables > Actions で設定します。

必須シークレット例:

| Secret 名 | 用途 | 例 | |-----------|------|----| | DATABASE_URL | DB 接続文字列 | postgresql://user:pass@host/db | | NEXT_PUBLIC_API_URL | API エンドポイント | https://api.example.com | | VERCEL_TOKEN | Vercel デプロイ | xxxxx | | AWS_ACCESS_KEY_ID | AWS 認証 | AKIAIOSFODNN7EXAMPLE | | AWS_SECRET_ACCESS_KEY | AWS 認証 | wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY |

ワークフローでの使用例

- name: Run E2E tests
  run: npm run test:e2e
  env:
    DATABASE_URL: ${{ secrets.DATABASE_URL }}
    NEXT_PUBLIC_API_URL: ${{ secrets.NEXT_PUBLIC_API_URL }}

Environment による環境別管理

ステージング・本番で異なる値を使う場合は Environment を活用します。

jobs:
  deploy:
    runs-on: ubuntu-latest
    environment: production  # Environment 名
    steps:
      - name: Deploy
        env:
          API_KEY: ${{ secrets.API_KEY }}  # production 環境の値が使われる

実務 Tips:

  • 環境ごとに Approval を設定すると、本番デプロイ前に手動承認を挟める
  • .env.example にキー一覧を記載し、ドキュメント化
  • ローカル開発用の .env.local.gitignore に追加

4. キャッシュ戦略による高速化

依存パッケージのキャッシュ

actions/setup-nodecache オプションが最もシンプルです。

- uses: actions/setup-node@v4
  with:
    node-version: '20'
    cache: 'npm'  # または 'yarn', 'pnpm'

ビルド成果物のキャッシュ

Next.js の .next ディレクトリなど、ビルド成果物もキャッシュできます。

- name: Cache Next.js build
  uses: actions/cache@v4
  with:
    path: |
      .next/cache
      node_modules/.cache
    key: ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json') }}-${{ hashFiles('**/*.js', '**/*.jsx', '**/*.ts', '**/*.tsx') }}
    restore-keys: |
      ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json') }}-
      ${{ runner.os }}-nextjs-

キャッシュの効果測定

| 項目 | キャッシュなし | キャッシュあり | 削減率 | |------|--------------|--------------|--------| | npm install | 45 秒 | 8 秒 | 82% | | Next.js build | 120 秒 | 70 秒 | 42% | | 合計 | 165 秒 | 78 秒 | 53% |


5. テストカバレッジとレポート表示

Jest でのカバレッジ収集

- name: Run tests with coverage
  run: npm run test:coverage

- name: Upload coverage to Codecov
  uses: codecov/codecov-action@v3
  with:
    token: ${{ secrets.CODECOV_TOKEN }}
    files: ./coverage/coverage-final.json
    fail_ci_if_error: true

PR コメントへの結果表示

actions/github-script を使うと、PR コメントにカバレッジを投稿できます。

- name: Comment coverage on PR
  uses: actions/github-script@v7
  with:
    script: |
      const fs = require('fs');
      const coverage = JSON.parse(fs.readFileSync('./coverage/coverage-summary.json', 'utf8'));
      const total = coverage.total;
      
      const comment = `## Test Coverage\n\n` +
        `- **Statements**: ${total.statements.pct}%\n` +
        `- **Branches**: ${total.branches.pct}%\n` +
        `- **Functions**: ${total.functions.pct}%\n` +
        `- **Lines**: ${total.lines.pct}%`;
      
      github.rest.issues.createComment({
        issue_number: context.issue.number,
        owner: context.repo.owner,
        repo: context.repo.repo,
        body: comment
      });

6. ステージング・本番環境へのデプロイ

Vercel へのデプロイ例

# .github/workflows/deploy-prod.yml
name: Deploy to Production

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    environment: production
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Deploy to Vercel
        uses: amondnet/vercel-action@v25
        with:
          vercel-token: ${{ secrets.VERCEL_TOKEN }}
          vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
          vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
          vercel-args: '--prod'

AWS S3 + CloudFront へのデプロイ

- name: Configure AWS credentials
  uses: aws-actions/configure-aws-credentials@v4
  with:
    aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
    aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
    aws-region: ap-northeast-1

- name: Build
  run: npm run build

- name: Deploy to S3
  run: |
    aws s3 sync ./out s3://${{ secrets.S3_BUCKET }} --delete

- name: Invalidate CloudFront cache
  run: |
    aws cloudfront create-invalidation \
      --distribution-id ${{ secrets.CLOUDFRONT_DISTRIBUTION_ID }} \
      --paths "/*"

デプロイ戦略の比較

| 戦略 | 実装方法 | メリット | 課題 | |------|---------|---------|------| | main マージ即デプロイ | on: push: branches: [main] | シンプル、速い | ロールバックが手動 | | タグベースデプロイ | on: push: tags: ['v*'] | リリースタイミング制御 | タグ作成が必要 | | 手動トリガー | on: workflow_dispatch | 完全制御 | 自動化されない | | Environment 承認 | environment: production | 本番前チェック | 承認待ちで遅延 |


7. マトリクステストとブランチ戦略

複数環境での並列テスト

strategy:
  matrix:
    os: [ubuntu-latest, windows-latest, macos-latest]
    node-version: [18.x, 20.x]
    include:
      - os: ubuntu-latest
        node-version: 20.x
        run-e2e: true  # Ubuntu + Node 20 でのみ E2E テスト実行

steps:
  - name: Run E2E tests
    if: matrix.run-e2e
    run: npm run test:e2e

ブランチ別の実行制御

on:
  push:
    branches:
      - main
      - develop
      - 'feature/**'
  pull_request:
    branches:
      - main
      - develop

jobs:
  quick-test:
    if: github.ref != 'refs/heads/main'
    runs-on: ubuntu-latest
    steps:
      - run: npm run test:unit  # 軽量テストのみ
  
  full-test:
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    steps:
      - run: npm run test        # 全テスト実行
      - run: npm run test:e2e

実務での使い分け:

  • Feature ブランチ: Lint + 単体テストのみ(5 分以内)
  • Develop ブランチ: 単体 + 統合テスト(10 分以内)
  • Main ブランチ: 全テスト + E2E + デプロイ(20 分以内)

8. トラブルシューティングとモニタリング

よくある失敗パターンと対処法

| 症状 | 原因 | 解決策 | |------|------|--------| | npm ci が失敗 | package-lock.json の不整合 | ローカルで npm install 後コミット | | キャッシュが効かない | key の指定ミス | hashFiles() でファイル変更を検知 | | シークレットが空 | Environment 未指定 | environment: production を追加 | | タイムアウト | デフォルト 360 分制限 | timeout-minutes: 30 で早期終了 | | 並列ジョブの依存関係 | needs 未指定 | needs: [test, build] で順序制御 |

デバッグ方法

- name: Debug environment
  run: |
    echo "Node version: $(node -v)"
    echo "NPM version: $(npm -v)"
    echo "Working directory: $(pwd)"
    ls -la
    printenv | grep -v SECRET  # シークレット以外の環境変数表示

Slack 通知の追加

- name: Notify Slack on failure
  if: failure()
  uses: slackapi/slack-github-action@v1
  with:
    payload: |
      {
        "text": "❌ Deployment failed: ${{ github.repository }}",
        "blocks": [
          {
            "type": "section",
            "text": {
              "type": "mrkdwn",
              "text": "*Workflow*: ${{ github.workflow }}\n*Branch*: ${{ github.ref }}"
            }
          }
        ]
      }
  env:
    SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}

9. コスト最適化のチェックリスト

GitHub Actions は Public リポジトリでは無料ですが、Private では月 2,000 分の制限があります。

コスト削減のための実践項目

  • [ ] キャッシュを活用:依存パッケージとビルド成果物をキャッシュ
  • [ ] 軽量ランナーを選択ubuntu-latestwindows-latest より 2 倍速い
  • [ ] 条件分岐で無駄な実行を削減:ドキュメント変更時はテストスキップ
  • [ ] 並列数を制限:Matrix の組み合わせを必要最小限に
  • [ ] タイムアウトを設定:無限ループ防止
  • [ ] Self-hosted Runner を検討:大規模プロジェクトでは自前サーバーが安い
on:
  push:
    paths-ignore:
      - '**.md'
      - 'docs/**'

jobs:
  test:
    timeout-minutes: 15  # デフォルト 360 分を短縮

まとめ

GitHub Actions による CI/CD パイプラインは、以下の手順で段階的に構築できます。

  1. 基本の CI ワークフロー:Lint・型チェック・テスト・ビルドを自動化
  2. キャッシュ戦略:npm ci とビルド成果物のキャッシュで 50% 高速化
  3. 環境変数管理:Repository Secrets と Environment で安全に管理
  4. デプロイ自動化:main マージで自動デプロイ、Environment で承認制御
  5. マトリクステスト:複数環境での並列テストでカバレッジ向上
  6. モニタリング:Slack 通知とカバレッジレポートで品質可視化

実務では、まず PR 時の自動テストから始め、安定したら自動デプロイへ拡張するアプローチが成功しやすいです。


Yureate では、CI/CD パイプライン構築や GitHub Actions を活用した開発フロー改善を支援しています。ご相談は お問い合わせページ からお気軽にどうぞ。

この内容について相談する他の記事を見る