EXERCISE 60分

総合演習:CI/CD + IaC 完全自動化

ストーリー

「ここまでの全てを組み合わせる。最終演習だ」

木村先輩が完成形のアーキテクチャ図を見せた。

「アプリケーションコードをpushしたらCIが走り、テストが通ったら 自動でビルドされる。インフラの変更はTerraformでPRベースで管理され、 マージしたら自動でapplyされる。 これが完全自動化パイプラインの完成形だ」

「アプリとインフラ、両方のCI/CDが一つのリポジトリで管理されるんですね」

「そうだ。モノレポでアプリとインフラのコードを一元管理する。 パスフィルタで、変更されたファイルに応じて 適切なパイプラインだけが実行される仕組みだ」


演習の概要

アプリケーションのCI/CDとインフラのIaCを統合した完全自動化パイプラインを設計・構築してください。

完成形のフロー

完全自動化パイプライン

┌──── アプリケーション変更 ────────────────────┐
│                                               │
│  src/ 以下の変更 → PR                         │
│    │                                          │
│    ├── CI: lint → test → build               │
│    │                                          │
│    └── マージ → CD: build → deploy           │
│                                               │
└───────────────────────────────────────────────┘

┌──── インフラ変更 ────────────────────────────┐
│                                               │
│  infrastructure/ 以下の変更 → PR              │
│    │                                          │
│    ├── CI: fmt → validate → plan → PRコメント │
│    │                                          │
│    └── マージ → CD: plan → apply             │
│                                               │
└───────────────────────────────────────────────┘

課題1: 統合リポジトリ構造の設計

アプリケーションとインフラを一元管理するリポジトリ構造を設計してください。

要件

  • アプリケーションコード(Node.js)
  • Terraformインフラコード
  • GitHub Actionsワークフロー(アプリ用、インフラ用)
  • パスフィルタで適切なワークフローのみ実行
<details> <summary>解答例(自分で実装してから確認しよう)</summary>
my-project/
├── .github/
│   └── workflows/
│       ├── app-ci.yml              # アプリCI(PRトリガー)
│       ├── app-cd.yml              # アプリCD(mainプッシュ)
│       ├── infra-plan.yml          # インフラplan(PRトリガー)
│       └── infra-apply.yml         # インフラapply(mainプッシュ)
├── app/
│   ├── src/
│   │   ├── index.ts
│   │   ├── routes/
│   │   └── services/
│   ├── tests/
│   │   ├── unit/
│   │   └── integration/
│   ├── Dockerfile
│   ├── package.json
│   └── tsconfig.json
├── infrastructure/
│   ├── modules/
│   │   ├── vpc/
│   │   ├── ec2/
│   │   ├── rds/
│   │   └── s3/
│   └── environments/
│       ├── staging/
│       └── production/
├── .gitignore
└── README.md
</details>

課題2: アプリケーションCI/CDワークフロー

app/ ディレクトリの変更に対して実行されるCI/CDワークフローを作成してください。

要件

  • CI: Lint → 型チェック → 単体テスト → ビルド → Dockerイメージビルド
  • CD: Dockerイメージビルド → ECRプッシュ(模擬) → デプロイ(模擬)
  • パスフィルタ: app/** のみ
  • キャッシュ: npm キャッシュを使用
<details> <summary>解答例(自分で実装してから確認しよう)</summary>
yaml
# .github/workflows/app-ci.yml
name: App CI

on:
  pull_request:
    branches: [main]
    paths: ['app/**']

permissions:
  contents: read

jobs:
  lint-and-test:
    name: Lint & Test
    runs-on: ubuntu-latest
    timeout-minutes: 15
    defaults:
      run:
        working-directory: app/
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'
          cache-dependency-path: app/package-lock.json
      - run: npm ci
      - run: npm run lint
      - run: npm run typecheck
      - run: npm test -- --coverage
      - uses: actions/upload-artifact@v4
        with:
          name: coverage
          path: app/coverage/
          retention-days: 7

  build:
    name: Build & Docker
    needs: lint-and-test
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: app/
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'
          cache-dependency-path: app/package-lock.json
      - run: npm ci
      - run: npm run build
      - name: Build Docker image
        run: docker build -t myapp:${{ github.sha }} .
      - name: Docker image size
        run: docker images myapp:${{ github.sha }} --format "{{.Size}}"
yaml
# .github/workflows/app-cd.yml
name: App CD

on:
  push:
    branches: [main]
    paths: ['app/**']

permissions:
  contents: read
  id-token: write

jobs:
  deploy:
    name: Build & Deploy
    runs-on: ubuntu-latest
    environment: staging
    timeout-minutes: 20
    defaults:
      run:
        working-directory: app/
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'
          cache-dependency-path: app/package-lock.json
      - run: npm ci
      - run: npm test
      - run: npm run build
      - name: Build Docker image
        run: |
          docker build \
            -t myapp:${{ github.sha }} \
            -t myapp:latest \
            .
      - name: Deploy (simulated)
        run: |
          echo "========================================="
          echo "  Deploying myapp:${{ github.sha }}"
          echo "  Environment: staging"
          echo "  Time: $(date -u)"
          echo "========================================="
</details>

課題3: 統合セキュリティチェック

アプリケーションとインフラ両方のセキュリティチェックを行うワークフローを作成してください。

要件

  • 毎週月曜日の定期実行(schedule)
  • アプリ: npm audit で依存パッケージの脆弱性チェック
  • インフラ: tfsec でTerraformコードのセキュリティスキャン
  • 結果をJob Summaryに出力
<details> <summary>解答例(自分で実装してから確認しよう)</summary>
yaml
# .github/workflows/security-scan.yml
name: Security Scan

on:
  schedule:
    - cron: '0 0 * * 1'     # 毎週月曜 0:00 UTC
  workflow_dispatch:          # 手動実行も可能

permissions:
  contents: read
  security-events: write

jobs:
  app-security:
    name: App Dependency Audit
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: app/
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
      - run: npm ci
      - name: Run npm audit
        run: |
          echo "## App Security Audit" >> $GITHUB_STEP_SUMMARY
          echo "" >> $GITHUB_STEP_SUMMARY
          npm audit --json > audit.json 2>&1 || true
          VULNERABILITIES=$(cat audit.json | jq '.metadata.vulnerabilities | to_entries[] | select(.value > 0) | "\(.key): \(.value)"' -r)
          if [ -z "$VULNERABILITIES" ]; then
            echo "No vulnerabilities found." >> $GITHUB_STEP_SUMMARY
          else
            echo "| Severity | Count |" >> $GITHUB_STEP_SUMMARY
            echo "|----------|-------|" >> $GITHUB_STEP_SUMMARY
            cat audit.json | jq -r '.metadata.vulnerabilities | to_entries[] | select(.value > 0) | "| \(.key) | \(.value) |"' >> $GITHUB_STEP_SUMMARY
          fi
        continue-on-error: true

  infra-security:
    name: Terraform Security Scan
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: tfsec scan
        uses: aquasecurity/tfsec-action@v1.0.3
        with:
          working_directory: infrastructure/
          soft_fail: true
      - name: Scan summary
        if: always()
        run: |
          echo "## Infrastructure Security Scan" >> $GITHUB_STEP_SUMMARY
          echo "" >> $GITHUB_STEP_SUMMARY
          echo "tfsec scan completed. Check the tfsec step output for details." >> $GITHUB_STEP_SUMMARY
</details>

達成度チェック

課題内容完了
課題1統合リポジトリ構造の設計[ ]
課題2アプリケーションCI/CDワークフロー[ ]
課題3統合セキュリティチェック[ ]

まとめ

ポイント内容
モノレポ構成app/ と infrastructure/ を一元管理
パスフィルタ変更されたディレクトリに応じて適切なワークフローを実行
アプリCI/CDテスト → ビルド → Dockerイメージ → デプロイ
セキュリティ定期的な脆弱性スキャンとIaCセキュリティチェック

チェックリスト

  • アプリとインフラを統合したリポジトリ構造を設計できた
  • パスフィルタで適切なワークフローのみを実行できる
  • アプリケーションのCI/CDパイプラインを構築できた
  • 定期的なセキュリティスキャンワークフローを作成できた
  • CI/CD + IaCの完全自動化パイプラインの全体像を説明できる

次のステップへ

総合演習が完了したら、卒業クイズに挑戦しましょう。 今月学んだ全ての内容を総合的にテストします。


推定所要時間: 60分