総合演習: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ワークフロー(アプリ用、インフラ用)
- パスフィルタで適切なワークフローのみ実行
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 キャッシュを使用
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 "========================================="課題3: 統合セキュリティチェック
アプリケーションとインフラ両方のセキュリティチェックを行うワークフローを作成してください。
要件
- 毎週月曜日の定期実行(schedule)
- アプリ: npm audit で依存パッケージの脆弱性チェック
- インフラ: tfsec でTerraformコードのセキュリティスキャン
- 結果をJob 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達成度チェック
| 課題 | 内容 | 完了 |
|---|---|---|
| 課題1 | 統合リポジトリ構造の設計 | [ ] |
| 課題2 | アプリケーションCI/CDワークフロー | [ ] |
| 課題3 | 統合セキュリティチェック | [ ] |
まとめ
| ポイント | 内容 |
|---|---|
| モノレポ構成 | app/ と infrastructure/ を一元管理 |
| パスフィルタ | 変更されたディレクトリに応じて適切なワークフローを実行 |
| アプリCI/CD | テスト → ビルド → Dockerイメージ → デプロイ |
| セキュリティ | 定期的な脆弱性スキャンとIaCセキュリティチェック |
チェックリスト
- アプリとインフラを統合したリポジトリ構造を設計できた
- パスフィルタで適切なワークフローのみを実行できる
- アプリケーションのCI/CDパイプラインを構築できた
- 定期的なセキュリティスキャンワークフローを作成できた
- CI/CD + IaCの完全自動化パイプラインの全体像を説明できる
次のステップへ
総合演習が完了したら、卒業クイズに挑戦しましょう。 今月学んだ全ての内容を総合的にテストします。
推定所要時間: 60分