Next.js: GitHub Actions を使用した CI/CD

最終更新:2026-08-26

CI/CD は開発チームにとっての「自動操縦装置」のようなものです — すべてのコミットが自動的に品質ゲートを通過し、合格したコードだけが本番環境にデプロイされます。

1. 学習内容



2. あるテクニカルマネージャーの実話

(1) 課題:手動デプロイ — 午前 3 時になってもまだターミナルを見つめている

Bob は TaskFlow チームのテクニカルリードで、10,000 人以上のユーザーにサービスを提供する SaaS プラットフォームを 5 人のメンバーで保守しています。毎週金曜日のリリースプロセスは次のようなものです:

"Alice が PR をマージ → Bob に通知 → Bob がローカルでテストを実行 → テストが通ったら手動で vercel deploy --prod をクリック → 10 分間ターミナルを見つめる → デプロイ成功を確認 → チームにメッセージを送信"

先週、Bob は npm run build の前に最新コードをプルするのを忘れたため、誤って古いバージョンをデプロイしてしまいました。5 分後にはユーザーがログインできなくなり、変更をロールバックするのにさらに 15 分かかりました。カスタマーサービスには 100 件以上の苦情が寄せられました。

課題 影響
手動デプロイ 人為的エラーの発生率が高い(リリースの 30% に問題あり)
自動アクセス制御テストなし 欠陥のあるコードでも本番環境に到達可能
環境不一致 ローカルでは動作するが本番環境でエラーが発生
PR プレビューなし マージ前に結果を確認できない

(2) GitHub Actions ソリューション

Bob は 3 つの自動化された組み立てラインを設計しました:

YAML
# PR が作成されるたび → 自動 lint + テスト + ビルド
# main にマージ → 自動ビルド + Vercel にデプロイ
# 毎日明け方 → 自動 Docker イメージビルド

(3) 成果

項目 手動デプロイ CI/CD 自動化
リリース時間 30 分 8 分
人為的エラー 30% < 1%
PR レビュー効率 コードのみ コード + プレビュー URL
デプロイ頻度 週 1 回 1 日 5 回


3. GitHub Actions の基礎

Actions は GitHub に組み込まれた CI/CD プラットフォームで、YAML ファイルを使用してワークフローを定義します。

100%
graph LR
    A[git push] --> B[GitHub Actions]
    B --> C[イベント トリガー]
    C --> D[ジョブ 並列/直列]
    D --> E[ステップ]
    E --> F[Actions マーケットプレイス コンポーネント]
    
    style B fill:#cce5ff
    style D fill:#d4edda
概念 説明
Workflow 1 つの YAML ファイル = 1 つの自動化プロセス .github/workflows/test.yml
Event ワークフローをトリガーするイベント pushpull_requestschedule
Job 一連のステップ(並列または依存関係あり) linttestdeploy
Step 単一のコマンドまたは Action npm run lintactions/checkout
Runner 実行環境 ubuntu-latestwindows-latest

(1) ワークフローファイルの構造

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

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

env:
  NODE_VERSION: '20'
  TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
      - run: npm ci
      - run: npm run lint

  test:
    needs: [lint]
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: ['18', '20', '22']
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
      - run: npm ci
      - run: npm test
      - run: npm run test:coverage
      - uses: codecov/codecov-action@v4
        with:
          token: ${{ secrets.CODECOV_TOKEN }}

  build:
    needs: [test]
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
      - run: npm ci
      - run: npm run build
      - uses: actions/upload-artifact@v4
        with:
          name: build-output
          path: .next/


4. test.yml: 並列マトリックステスト

100%
graph TB
    A[Git Push / PR] --> B[lint]
    B --> C[test 18.x]
    B --> D[test 20.x]
    B --> E[test 22.x]
    C --> F[build]
    D --> F
    E --> F
    F --> G[ビルド成果物のアップロード]
    
    style A fill:#cce5ff
    style C fill:#d4edda
    style D fill:#d4edda
    style E fill:#d4edda

(1) 完全な test.yml

YAML
# .github/workflows/test.yml
name: Test Suite

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

jobs:
  lint:
    name: Lint Check
    runs-on: ubuntu-latest
    timeout-minutes: 10
    steps:
      - uses: actions/checkout@v4
      
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'
          
      - name: 依存関係のインストール
        run: npm ci
          
      - name: TypeScript 型チェック
        run: npx tsc --noEmit
        
      - name: ESLint チェック
        run: npm run lint
        
      - name: Prettier チェック
        run: npx prettier --check "src/**/*.{ts,tsx}"

  unit-and-integration:
    name: ユニットテスト & 統合テスト
    needs: [lint]
    runs-on: ubuntu-latest
    timeout-minutes: 15
    
    strategy:
      matrix:
        node-version: ['18', '20', '22']
      fail-fast: false
    
    services:
      postgres:
        image: postgres:16-alpine
        env:
          POSTGRES_USER: test
          POSTGRES_PASSWORD: test
          POSTGRES_DB: testdb
        ports:
          - 5432:5432
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
    
    steps:
      - uses: actions/checkout@v4
      
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
          cache: 'npm'
          
      - name: 依存関係のインストール
        run: npm ci
          
      - name: Prisma クライアントの生成
        run: npx prisma generate
          
      - name: データベースマイグレーションの実行
        run: npx prisma migrate deploy
        env:
          DATABASE_URL: postgresql://test:test@localhost:5432/testdb
          
      - name: ユニットテストの実行
        run: npm run test
        env:
          DATABASE_URL: postgresql://test:test@localhost:5432/testdb
          
      - name: 統合テストの実行
        run: npm run test:integration
        env:
          DATABASE_URL: postgresql://test:test@localhost:5432/testdb
          
      - name: カバレッジのアップロード
        uses: codecov/codecov-action@v4
        with:
          token: ${{ secrets.CODECOV_TOKEN }}
          flags: unittests
          name: codecov-node-${{ matrix.node-version }}

  e2e:
    name: E2E テスト
    needs: [lint]
    runs-on: ubuntu-latest
    timeout-minutes: 20
    
    steps:
      - uses: actions/checkout@v4
      
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'
          
      - name: 依存関係のインストール
        run: npm ci
          
      - name: Playwright ブラウザのインストール
        run: npx playwright install --with-deps chromium
        
      - name: E2E テストの実行
        run: npx playwright test --project=chromium
        env:
          TEST_DATABASE_URL: ${{ secrets.TEST_DATABASE_URL }}
          
      - uses: actions/upload-artifact@v4
        if: failure()
        with:
          name: playwright-report
          path: playwright-report/
          retention-days: 7

  build:
    name: ビルドチェック
    needs: [unit-and-integration]
    runs-on: ubuntu-latest
    timeout-minutes: 10
    
    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: next-build
          path: .next/
          retention-days: 1

▶ サンプル: マトリックス並列テスト結果

TEXT 📖 参照専用
# GitHub Actions コンソール出力
Job: unit-and-integration (node-version: 18.x)  ✓ 3m 12s
Job: unit-and-integration (node-version: 20.x)  ✓ 2m 58s
Job: unit-and-integration (node-version: 22.x)  ✓ 3m 05s

Summary:
  ✓ lint                        (1 job)  0m 45s
  ✓ unit-and-integration        (3 jobs) 3m 12s
  ✓ e2e                         (1 job)  4m 30s
  ✓ build                       (1 job)  1m 20s


5. deploy.yml: Vercel への自動デプロイ

デプロイメント環境 トリガー条件 対象
プレビュー PR 作成/更新 プレビューブランチにデプロイ
本番 main にマージ 本番環境の更新
ステージング リリースタグ リリース前の検証

(1) Vercel デプロイ設定

YAML
# .github/workflows/deploy.yml
name: Deploy to Vercel

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

env:
  VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
  VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}

jobs:
  deploy-preview:
    name: プレビューのデプロイ
    if: github.event_name == 'pull_request'
    runs-on: ubuntu-latest
    timeout-minutes: 15
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Vercel CLI のインストール
        run: npm install --global vercel@latest
      
      - name: Vercel 環境のプル
        run: vercel pull --yes --environment=preview --token=${{ secrets.VERCEL_TOKEN }}
        
      - name: プロジェクト成果物のビルド
        run: vercel build --token=${{ secrets.VERCEL_TOKEN }}
        
      - name: Vercel プレビューにデプロイ
        run: |
          vercel deploy --prebuilt --token=${{ secrets.VERCEL_TOKEN }} > deployment-url.txt
          echo "PREVIEW_URL=$(cat deployment-url.txt)" >> $GITHUB_ENV
      
      - name: PR にプレビュー URL をコメント
        uses: thollander/actions-comment-pull-request@v2
        with:
          message: |
            🚀 **プレビューデプロイメント準備完了**
            
            | 環境 | URL |
            |:-----------|:----|
            | プレビュー | ${{ env.PREVIEW_URL }} |
            | ブランチ | ${{ github.head_ref }} |
            
            _このコメントはプッシュのたびに自動更新されます。_

  deploy-production:
    name: 本番環境へのデプロイ
    if: github.event_name == 'push' && github.ref == 'refs/heads/main'
    needs: [deploy-preview]
    runs-on: ubuntu-latest
    timeout-minutes: 15
    environment: production
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Vercel CLI のインストール
        run: npm install --global vercel@latest
      
      - name: Vercel 環境のプル
        run: vercel pull --yes --environment=production --token=${{ secrets.VERCEL_TOKEN }}
        
      - name: プロジェクト成果物のビルド
        run: vercel build --prod --token=${{ secrets.VERCEL_TOKEN }}
        
      - name: Vercel 本番環境にデプロイ
        run: vercel deploy --prebuilt --prod --token=${{ secrets.VERCEL_TOKEN }}
      
      - name: デプロイ成功を通知
        uses: slackapi/slack-github-action@v1
        with:
          payload: |
            {
              "text": "✅ 本番デプロイメント完了: ${{ github.repository }}@${{ github.sha }}"
            }
        env:
          SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}


6. Docker イメージビルド(マルチステージ、358 MB)

セルフホストデプロイメントでは、CI で Docker イメージを自動ビルドする必要があります。

(1) マルチステージ Dockerfile

DOCKERFILE
# Dockerfile — Next.js 16 スタンドアロンビルドイメージ
# フェーズ 1: 依存関係のインストール(キャッシュレイヤーを使用)
FROM node:20-alpine AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --only=production && \
    npm cache clean --force

# フェーズ 2: ビルド(.next 成果物を生成)
FROM node:20-alpine AS build
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
ENV NEXT_TELEMETRY_DISABLED=1
RUN npm run build

# フェーズ 3: 実行(最小化イメージ ~358MB)
FROM node:20-alpine AS runner
WORKDIR /app

ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1

RUN addgroup --system --gid 1001 nodejs && \
    adduser --system --uid 1001 nextjs

COPY --from=build /app/public ./public
COPY --from=build --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=build --chown=nextjs:nodejs /app/.next/static ./.next/static

USER nextjs

EXPOSE 3000

ENV PORT=3000
ENV HOSTNAME="0.0.0.0"

CMD ["node", "server.js"]

(2) Docker ビルド Action

YAML
# .github/workflows/docker.yml
name: Docker Build & Push

on:
  push:
    tags: ['v*']
  schedule:
    - cron: '0 2 * * 0'  # 毎週日曜日早朝 2 時

jobs:
  docker:
    runs-on: ubuntu-latest
    timeout-minutes: 30
    
    steps:
      - uses: actions/checkout@v4
      
      - name: QEMU のセットアップ
        uses: docker/setup-qemu-action@v3
      
      - name: Docker Buildx のセットアップ
        uses: docker/setup-buildx-action@v3
      
      - name: GitHub Container Registry にログイン
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      
      - name: Docker メタデータ
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: ghcr.io/${{ github.repository }}
          tags: |
            type=semver,pattern={{version}}
            type=semver,pattern={{major}}.{{minor}}
            type=sha,format=short
            type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }}
      
      - name: ビルドとプッシュ
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

▶ サンプル: Docker イメージビルドの出力

TEXT 📖 参照専用
# ビルドログ
#1 [deps 1/1] RUN npm ci --only=production
#1 DONE 15.2s

#2 [build 1/4] COPY --from=deps /app/node_modules ./node_modules
#2 DONE 0.1s

#3 [build 2/4] COPY . .
#3 DONE 0.3s

#4 [build 3/4] RUN npm run build
#4 DONE 28.5s

#5 [runner 1/6] COPY --from=build /app/public ./public
#5 DONE 0.1s

#6 Exporting layers
#6 DONE 3.2s

# イメージサイズの分析
ghcr.io/myorg/taskflow:latest   358 MB


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

100%
graph TB
    A[GitHub Secrets] --> B[Actions Runtime]
    B --> C[Vercel Token]
    B --> D[データベース URL]
    B --> E[API キー]
    B --> F[Slack Webhook]
    C --> G[Vercel にデプロイ]
    D --> H[テスト実行]
    E --> I[ビルド時に注入]
    F --> J[デプロイ通知]
    
    style A fill:#cce5ff
    style B fill:#d4edda
環境変数名 目的 ソース
VERCEL_TOKEN Vercel API 認証 GitHub Secrets
VERCEL_ORG_ID Vercel チーム ID Vercel ダッシュボード
VERCEL_PROJECT_ID Vercel プロジェクト ID Vercel ダッシュボード
DATABASE_URL データベース接続 GitHub Secrets
CODECOV_TOKEN カバレッジのアップロード Codecov ウェブサイト
SLACK_WEBHOOK_URL デプロイ通知 Slack アプリ設定

(1) GitHub Secrets の設定

BASH
# GitHub リポジトリ → Settings → Secrets and variables → Actions → 追加

gh secret set VERCEL_TOKEN --body "your-vercel-token"
gh secret set DATABASE_URL --body "postgresql://user:pass@host:5432/db"
gh secret set SLACK_WEBHOOK_URL --body "https://hooks.slack.com/services/..."

(2) 環境分離戦略

YAML
# 異なる環境での変数オーバーライド
jobs:
  test:
    env:
      DATABASE_URL: postgresql://test:test@localhost:5432/testdb
      NODE_ENV: test
      
  deploy-preview:
    environment: preview
    env:
      DATABASE_URL: ${{ secrets.PREVIEW_DATABASE_URL }}
      NEXT_PUBLIC_API_URL: ${{ vars.PREVIEW_API_URL }}
      
  deploy-production:
    environment: production
    env:
      DATABASE_URL: ${{ secrets.PROD_DATABASE_URL }}
      NEXT_PUBLIC_API_URL: https://api.taskflow.io


8. PR プレビューデプロイメントワークフロー

PR プレビューを使用すると、開発者はマージ前に変更の効果をプレビューできます。

100%
graph TB
    A[開発者が PR を作成] --> B[Actions が deploy-preview をトリガー]
    B --> C[Vercel がプレビューデプロイメントを作成]
    C --> D[プレビュー URL を生成]
    D --> E[ボットが PR にリンクをコメント]
    E --> F[レビュアーがプレビューで検証]
    F -->|承認| G[main にマージ]
    G --> H[Actions が deploy-production をトリガー]
    
    style A fill:#cce5ff
    style F fill:#fff3cd
    style H fill:#d4edda

▶ サンプル: 完全な PR プレビュー + クリーンアップワークフロー

💻 出力:

TEXT 📖 参照専用
上記の YAML 設定を指定されたファイルパスに保存してください。設定は次回のサーバー再起動時に有効になります。
YAML
# .github/workflows/preview.yml
name: PR Preview

on:
  pull_request:
    types: [opened, synchronize, closed]

jobs:
  preview:
    if: github.event.action != 'closed'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Vercel プレビューにデプロイ
        id: deploy
        run: |
          npx vercel --token=${{ secrets.VERCEL_TOKEN }} \
            --scope=${{ secrets.VERCEL_ORG_ID }} \
            --confirm > preview-url.txt
          echo "url=$(cat preview-url.txt)" >> $GITHUB_OUTPUT
      
      - name: URL をコメント
        uses: actions/github-script@v7
        with:
          script: |
            const url = '${{ steps.deploy.outputs.url }}'
            github.rest.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: `🚀 **プレビューがデプロイされました**\n\n${url}\n\n_コミット: ${context.sha}_`
            })

  cleanup:
    if: github.event.action == 'closed'
    runs-on: ubuntu-latest
    steps:
      - name: Vercel プレビューを削除
        run: |
          npx vercel remove \
            taskflow-git-${GITHUB_HEAD_REF//\//-} \
            --token=${{ secrets.VERCEL_TOKEN }} \
            --yes --scope=${{ secrets.VERCEL_ORG_ID }} || true
💻 出力:

TEXT 📖 参照専用
セクション: name、on、jobs。


9. 完全な例: TaskFlow 完全 CI/CD パイプライン

YAML
# .github/workflows/full-pipeline.yml
# ============================================
# TaskFlow 完全 CI/CD 組み立てライン
# ============================================
name: TaskFlow Full Pipeline

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]
  release:
    types: [published]

env:
  NODE_VERSION: '20'
  PNPM_VERSION: '9'

jobs:
  # === フェーズ 1: 品質アクセス制御 ===
  quality-gate:
    name: 品質ゲート
    runs-on: ubuntu-latest
    timeout-minutes: 10
    
    steps:
      - uses: actions/checkout@v4
      
      - uses: pnpm/action-setup@v4
        with:
          version: ${{ env.PNPM_VERSION }}
      
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: 'pnpm'
      
      - run: pnpm install --frozen-lockfile
      
      - name: TypeScript チェック
        run: pnpm typecheck
        
      - name: ESLint + Prettier
        run: pnpm lint && pnpm format:check
        
      - name: カバレッジ付きユニットテスト
        run: pnpm test:coverage
        
      - name: カバレッジのアップロード
        uses: codecov/codecov-action@v4
        with:
          token: ${{ secrets.CODECOV_TOKEN }}
          fail_ci_if_error: false

  # === フェーズ 2: 統合テスト ===
  integration:
    name: 統合テスト
    needs: [quality-gate]
    runs-on: ubuntu-latest
    timeout-minutes: 20
    
    services:
      postgres:
        image: postgres:16-alpine
        env:
          POSTGRES_USER: taskflow
          POSTGRES_PASSWORD: taskflow
          POSTGRES_DB: taskflow_test
        ports:
          - 5432:5432
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
    
    steps:
      - uses: actions/checkout@v4
      - uses: pnpm/action-setup@v4
        with:
          version: ${{ env.PNPM_VERSION }}
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: 'pnpm'
      
      - run: pnpm install --frozen-lockfile
      - run: npx prisma generate
      - run: npx prisma migrate deploy
        env:
          DATABASE_URL: postgresql://taskflow:taskflow@localhost:5432/taskflow_test
      
      - name: 統合テスト
        run: pnpm test:integration
        env:
          DATABASE_URL: postgresql://taskflow:taskflow@localhost:5432/taskflow_test
      
      - name: E2E テスト
        run: npx playwright install --with-deps chromium && pnpm test:e2e
        env:
          DATABASE_URL: postgresql://taskflow:taskflow@localhost:5432/taskflow_test

  # === フェーズ 3: ビルド ===
  build:
    name: アプリケーションのビルド
    needs: [integration]
    runs-on: ubuntu-latest
    timeout-minutes: 15
    outputs:
      image-tag: ${{ steps.meta.outputs.tags }}
    
    steps:
      - uses: actions/checkout@v4
      - uses: pnpm/action-setup@v4
        with:
          version: ${{ env.PNPM_VERSION }}
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: 'pnpm'
      
      - run: pnpm install --frozen-lockfile
      - run: pnpm build
      
      - name: Docker イメージのビルド
        if: github.event_name == 'push'
        uses: docker/build-push-action@v5
        with:
          context: .
          load: true
          tags: taskflow:ci-${{ github.sha }}
      
      - name: ビルド成果物の保存
        uses: actions/upload-artifact@v4
        with:
          name: build-artifacts
          path: |
            .next/
            public/
            package.json

  # === フェーズ 4: デプロイメント ===
  deploy:
    name: デプロイ
    needs: [build]
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    environment: production
    timeout-minutes: 15
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Vercel にデプロイ
        run: |
          npx vercel deploy --prod \
            --token=${{ secrets.VERCEL_TOKEN }} \
            --scope=${{ secrets.VERCEL_ORG_ID }}
      
      - name: Slack に通知
        uses: slackapi/slack-github-action@v1
        with:
          payload: |
            {
              "text": "✅ TaskFlow が本番環境にデプロイされました\nコミット: ${{ github.sha }}\n実行者: ${{ github.actor }}"
            }
        env:
          SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
      
      - name: Lighthouse CI の実行
        run: npx lhci autorun
        env:
          LHCI_GITHUB_APP_TOKEN: ${{ secrets.LHCI_GITHUB_TOKEN }}

❓ よくある質問

Q GitHub Actions の無料枠は十分ですか?
A GitHub Free プランでは月間 2,000 分の Actions 実行時間が提供されます(パブリックリポジトリは無制限です)。一般的な Next.js の CI パイプラインは 1 回あたり約 8〜12 分かかりますので、2,000 分で月間約 200 回の実行が可能です。さらに必要な場合は、GitHub Team で月間 3,000 分が提供されます。また、独自のランナーをセルフホストでセットアップすることもできます。
Q 複数の Node.js バージョンでマトリックステストを行う必要があるのはなぜですか?
A ユーザーは様々な Node バージョンでアプリケーションを実行している可能性があります(Vercel は 18.x を使用し、Docker では 20.x または 22.x を使用する場合があります)。マトリックステストは、サポートされているすべての Node バージョンでコードが正しく動作することを保証します。Next.js 16 は公式に Node 18.17 以降をサポートしており、最新の 3 つの LTS バージョンをテストすることがベストプラクティスです。
Q vercel-action と Vercel CLI のどちらが優れていますか?
A vercel-actionamondnet/vercel-action)は一般的な CLI 操作をラップしますが、アップデートが遅れる場合があります。Vercel CLI(npm install -g vercel)を直接使用することをお勧めします。Actions で run: vercel deploy --prod --token=... を使用することで、より柔軟性が高く、常に最新バージョンを使用できます。
Q シークレットの漏洩を防ぐにはどうすればよいですか?
A (1) YAML に平文で保存するのではなく、GitHub Encrypted Secrets を使用します。(2) フォークからのプルリクエストに対する自動シークレット注入を無効にします(Settings → Actions → Fork pull request workflows)。(3) シークレットを定期的にローテーションします。(4) actions/secrets-scanning を使用して誤ったコミットを検出します。
Q PR プレビューと Vercel のデフォルトプレビューの違いは何ですか?
A Vercel は各 PR に対して自動的にプレビューデプロイメントを作成しますが(Git と統合されています)、URL を表示するには Vercel ダッシュボードにログインする必要があります。GitHub Actions で手動デプロイし、PR に URL をコメントすることで、チームメンバーは PR ページから直接クリックしてアクセスでき、より優れた体験が得られます。
Q 遅い CI パイプラインを最適化するにはどうすればよいですか?
A (1) actions/cache を使用して node_modules.next/cache をキャッシュします。(2) 独立したジョブを並列実行します。(3) fail-fast: false を使用して、単一バージョンの失敗がパイプライン全体のキャンセルを引き起こさないようにします。(4) npm の代わりに pnpm を使用します(インストールが高速です)。(5) リポジトリが大きい場合はランナーをセルフホストします。

📖 まとめ


📝 練習問題

  1. 基本問題 (⭐): .github/workflows/ci.yml を作成し、Lint、Test、Build の 3 つの直列ジョブを含め、main への push ごとにトリガーするようにします。

  2. 応用問題 (⭐⭐): プロジェクトに完全な Vercel 自動デプロイパイプラインをセットアップします:(1) GitHub Secrets に VERCEL_TOKEN を設定する。(2) PR プレビューと本番デプロイを実装する deploy.yml を記述する。(3) プレビュー URL が PR コメントに表示されることを確認する。

  3. 発展問題 (⭐⭐⭐): マルチ環境 CI/CD パイプライン(dev → staging → production)を実装します:(1) 各環境に独自のデータベースとシークレットを持たせる。(2) dev ブランチは自動的に dev 環境にデプロイされる。(3) main ブランチは自動的に staging にデプロイされる。(4) 本番環境へのデプロイには手動承認が必要。(5) デプロイ成功後に webhook 経由で Slack チャンネルに通知する。

Web-Tutorial.com

Web-Tutorial 技術チーム

複数の開発者によって共同維持されているプログラミングチュートリアルプラットフォーム。各チュートリアルは専門分野の開発者が執筆・レビューしています。正確で信頼性の高いコンテンツを目指しています — 問題を見つけた場合はお知らせください。

100%