CircleCIでテスト・ビルドしてNetlifyに自動デプロイする方法【React / Vite】

NetlifyにデプロイしているReactアプリに、CircleCIを使ったCI/CDパイプラインを導入する手順

「テストが通ったときだけデプロイしたい」という要件を、実際のハマりどころも含めてまとめた。


なぜCircleCIを導入するのか

Netlifyはgit pushを検知すると即座にビルド・デプロイを開始する。つまり、CircleCIでテストが走っている最中にNetlifyのデプロイが完了してしまう。

git push

├── Netlify: 即座にbuild & deploy開始(テスト関係なし)

└── CircleCI: test実行中…(後から完了)

テストが失敗してもNetlifyはすでにデプロイ済み、という状態になるため、CircleCIでテストとビルドを管理し、成功時のみNetlifyへデプロイする構成が必要。

構成の全体像

git push → CircleCI起動
└── test ジョブ(全ブランチ)

├── Lint

└── Build

└── 成功時のみ

└── deploy ジョブ(mainブランチのみ)

└── netlify-cli でデプロイ


事前準備

1. Netlifyの自動ビルドを無効化する

CircleCIでビルドを管理するため、NetlifyのビルドをOFFにする。

以下の設定画面は、Netlify上で検索したり、AIエージェントに場所を聞いたりできる。

Netlify管理画面`Site configuration` `Build & deploy``Continuous deployment` `Stop builds`

また、`Build command`フィールドも空にしておく。空にしない場合、netlify-cliがNetlify UIの設定を読み込んでビルドを実行しようとする場合がある。

2. netlify.tomlをプロジェクトルートに追加する (これはなくてもいいかも)

netlify.tomlを追加することで、Netlify UIの設定より優先してビルドコマンドを上書きできる。CircleCIがビルド済みの`dist/`をアップロードするので、buildコマンドは不要。

```toml
[build]

publish = "dist"

# buildコマンドは空(CircleCIがビルド済みのdist/をデプロイするため不要)

3. NetlifyのアクセストークンとサイトIDを取得する

Netlify Auth Token

– Netlify管理画面 → `User settings` → `Applications` → `Personal access tokens`

Site ID

– Netlify管理画面 → `Site configuration` → `General` → `Site details` → `Project ID (Site ID)`

4. CircleCIの環境変数に登録する

CircleCIのプロジェクト設定に以下の環境変数を追加します。

– `Project Settings` → `Environment Variables`

– `NETLIFY_AUTH_TOKEN` ← 取得したトークン

– `NETLIFY_SITE_ID` ← 取得したサイトID

CircleCIの設定ファイル(.circleci/config.yml)

config.yml
version: 2.1

jobs:
  # ----------------------------
  # テストジョブ
  # Lintチェックとビルド確認を行う
  # (Jestを導入したら unit tests ステップを追加する)
  # ----------------------------
  test:
    docker:
      - image: cimg/node:22.0  # Node.js 22 の公式CircleCIイメージ
    steps:
      - checkout  # リポジトリのコードを取得

      # node_modulesをキャッシュから復元(package-lock.jsonが変わると無効)
      - restore_cache:
          keys:
            - v1-deps-{{ checksum "package-lock.json" }}

      - run: npm ci  # package-lock.jsonに基づいてクリーンインストール

      # キャッシュを保存(次回以降のビルドを高速化)
      - save_cache:
          paths:
            - node_modules
          key: v1-deps-{{ checksum "package-lock.json" }}

      - run:
          name: Lint  # ESLintでコード品質チェック
          command: npm run lint

      - run:
          name: Build  # ビルドが成功するか確認
          command: npm run build

  # ----------------------------
  # デプロイジョブ
  # testジョブが成功した場合のみ実行される
  # 事前にCircleCIの環境変数に以下を設定すること:
  #   NETLIFY_AUTH_TOKEN: Netlifyのパーソナルアクセストークン
  #   NETLIFY_SITE_ID: NetlifyのサイトID
  # ----------------------------
  deploy:
    docker:
      - image: cimg/node:22.0
    steps:
      - checkout

      # deployジョブでも依存関係をインストール(viteが必要)
      - restore_cache:
          keys:
            - v1-deps-{{ checksum "package-lock.json" }}

      - run: npm ci

      - run:
          name: Build  # デプロイ用にビルド
          command: npm run build

      - run:
          name: Deploy to Netlify  # Netlify CLIでプロダクション環境にデプロイ
          command: npx netlify-cli deploy --prod --dir=dist

workflows:
  ci:
    jobs:
      - test  # 全ブランチでテスト実行

      - deploy:
          requires:
            - test  # testジョブが成功した場合のみデプロイ
          filters:
            branches:
              only: main  # mainブランチへのpushのみデプロイ

ハマりどころと解決策

`vite: not found` エラー

“`

sh: 1: vite: not found

“build.command” failed

“`

**原因**: NetlifyはデフォルトでNODE_ENV=productionで`npm install`を実行するため、`devDependencies`をインストールしない。`vite`は`devDependencies`に入っているため見つからない。

**解決策**:

– Netlifyの自動ビルドを無効化し、CircleCIからデプロイする

– `netlify.toml`でbuildコマンドを空にする

② netlify-cliが勝手にビルドを実行する

`netlify deploy –prod –dir=dist`を指定しているのに、netlify-cliがNetlify UIのbuild commandを読み込んで`npm run build`を実行してしまうケースがある。

**原因**: Netlify UIのbuild commandが設定されていると、netlify-cliがそれを実行する。

**解決策**:

– Netlify UIのbuild commandを空にする

– `netlify.toml`を追加してUI設定を上書きする

`dist/`フォルダが引き継がれない問題

CircleCIの`persist_to_workspace` / `attach_workspace`で`dist/`を引き継ぐ構成にした場合、netlify-cliが`dist/`を見つけられず、ビルドを実行しようとするケースがある。

**解決策**: workspaceの引き継ぎをやめ、deployジョブでも`npm ci`と`npm run build`を実行する構成にする。ビルドが2回走るが、キャッシュを共有しているため速度への影響は最小限。この構成の場合、netlify.tomlは不要。

Jestでユニットテストを追加する場合

現在の構成にJestを追加するときは、testジョブのLintステップの後に追加するだけ。

run:
    name: Unit tests
    command: npm test -- --ci --coverage

Reactプロジェクトでテストを書く場合のおすすめセットアップ:

“`bash

npm install --save-dev jest @testing-library/react @testing-library/jest-dom jest-environment-jsdom

まとめ

項目設定
Netlify自動ビルドStop builds(無効化)
Netlify build command空にする
netlify.tomlpublish = “dist”のみ
CircleCI testジョブLint + Build(全ブランチ)
CircleCI deployジョブnpm ci + Build + netlify deploy(mainのみ)

この構成により、mainブランチへのpushに対して「テスト・ビルドが通ったときだけデプロイ」が保証される。

*技術スタック: React / Vite / CircleCI / Netlify*

タグ: