Vercel Pro プランで複数環境(dev/stg/prd)を GitHub Actions で実現した
に公開
に公開
Next.js プロジェクトを Vercel にデプロイする際、開発(dev)、ステージング(stg)、本番(prd)の3環境を構築しようとしたところ、Vercel Pro プランの制約にぶつかりました。
この記事では、その制約を GitHub Actions で回避して複数環境を実現した方法を紹介していきます。
dev ブランチ → dev 環境(開発用)
stg ブランチ → stg 環境(ステージング)
main ブランチ → prd 環境(本番)加えて、PR 作成時には対応する環境のプレビューデプロイも行いたい。
Vercel には以下の環境が用意されています:
| 環境 | 説明 |
|---|---|
| Production | 本番環境(組み込み) |
| Preview | PR プレビュー用(組み込み) |
| Development | ローカル開発用(組み込み) |
| Custom Environment | 追加の環境(Pro プランでは1つまで) |
つまり、Pro プランでは Production + Custom Environment の2環境 しか作れません。dev / stg / prd の3環境を1つのプロジェクトで管理するのは不可能でした。
Vercel の Preview 環境は便利なのですが、大きな制約があります。
環境変数が固定で、PR のターゲットブランチに応じて切り替えられない。
例えば:
feature/xxx → dev の PR → dev 用の環境変数を使いたいrelease/xxx → main の PR → prd 用の環境変数を使いたいしかし Vercel の Preview 環境変数は1セットしか設定できないため、どちらかが正常に動かなくなります。
Vercel の自動デプロイ機能を使わず、GitHub Actions + Vercel CLI でデプロイを制御することにしました。
Vercel プロジェクト構成
| プロジェクト | 環境 | 対応ブランチ |
|---|---|---|
| hanasho-ec-web(メイン) | Production | main |
| hanasho-ec-web(メイン) | Custom Environment (stg) | stg |
| hanasho-ec-web-dev(別プロジェクト) | Production | dev |
GitHub Environments 構成
| Environment | 用途 | 備考 |
|---|---|---|
| dev | CD 用 | hanasho-ec-web-dev の secrets |
| stg | CD 用 | |
| production | CD 用 | |
| preview-dev | Preview 用 | dev 環境の secrets |
| preview-stg | Preview 用 | |
| preview-prd | Preview 用 |
dev だけ別プロジェクト
環境変数は GitHub Secrets で管理
vercel env pull)はやめたPreview 用の Environment を別途作成
preview-dev, preview-stg, preview-prd を作成.github/
├── actions/
│ └── create-env/
│ └── action.yml # .env 作成(Composite Action)
└── workflows/
├── hanasho-ec-web_cicd.yml # CI/CD メイン
├── hanasho-ec-web_preview.yml # Preview
├── _deploy.yml # CD 共通処理(Reusable Workflow)
└── _preview.yml # Preview 共通処理(Reusable Workflow)# hanasho-ec-web_cicd.yml
name: Hanasho EC Web CI/CD
on:
push:
branches: [main, stg, dev]
pull_request:
types: [opened, reopened, synchronize]
jobs:
setup:
# node_modules のキャッシュ作成
type-check:
needs: setup
# 型チェック(並列実行)
lint:
needs: setup
# Lint(並列実行)
test:
needs: setup
# テスト(並列実行)
deploy:
name: CD (${{ github.ref_name }})
needs: [type-check, lint, test]
if: github.event_name == 'push'
uses: ./.github/workflows/_deploy.yml
with:
# 三項演算子で環境を動的に決定
environment: ${{ github.ref_name == 'main' && 'production' || github.ref_name == 'stg' && 'stg' || 'dev' }}
vercel_env: ${{ github.ref_name == 'stg' && 'stg' || 'production' }}
secrets: inherit# _deploy.yml
name: Deploy
on:
workflow_call:
inputs:
environment:
required: true
type: string
vercel_env:
required: true
type: string
jobs:
deploy:
runs-on: ubuntu-latest
environment: ${{ inputs.environment }}
env:
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '24.13.0'
cache: 'npm'
- run: npm install -g vercel
- run: vercel pull --yes --token=${{ secrets.VERCEL_TOKEN }}
# Composite Action で .env 作成
- uses: ./.github/actions/create-env
with:
api_base_url: ${{ secrets.API_BASE_URL }}
api_key: ${{ secrets.API_KEY }}
app_env: ${{ secrets.APP_ENV }}
- name: Build
run: |
vercel build \
${{ inputs.vercel_env == 'production' && '--prod' || '' }} \
--token=${{ secrets.VERCEL_TOKEN }}
- name: Deploy
run: |
vercel deploy --prebuilt \
${{ inputs.vercel_env == 'production' && '--prod' || '' }} \
--token=${{ secrets.VERCEL_TOKEN }}# .github/actions/create-env/action.yml
name: 'Create .env file'
inputs:
api_base_url:
required: true
api_key:
required: true
app_env:
required: true
runs:
using: 'composite'
steps:
- shell: bash
run: |
cat <<EOF > .env
API_BASE_URL=${{ inputs.api_base_url }}
API_KEY=${{ inputs.api_key }}
APP_ENV=${{ inputs.app_env }}
EOF# hanasho-ec-web_preview.yml
name: Hanasho EC Web Preview
on:
pull_request:
types: [opened, reopened, synchronize]
jobs:
preview:
name: Preview (${{ github.base_ref }})
uses: ./.github/workflows/_preview.yml
with:
# PR のターゲットブランチに応じて環境を決定
environment: ${{ github.base_ref == 'main' && 'preview-prd' || github.base_ref == 'stg' && 'preview-stg' || 'preview-dev' }}
secrets: inherit今回、両方を使い分けました。
| 種類 | 用途 | secrets の扱い |
|---|---|---|
| Reusable Workflow | ジョブ全体の共通化 | secrets: inherit で継承可能 |
| Composite Action | ステップの共通化 | with: で個別に渡す |
.env 作成は Composite Action にしています。これにより _deploy.yml と _preview.yml の両方から呼び出せて、環境変数を追加する時は action.yml だけ変更すればOKです。
最初は環境ごとにジョブを分けていました:
# Before: 3つのジョブが常に表示される
jobs:
cd-dev:
if: github.ref_name == 'dev'
cd-stg:
if: github.ref_name == 'stg'
cd-prd:
if: github.ref_name == 'main'この場合、dev ブランチに push しても cd-stg と cd-prd が "Skipped" として表示されてしまいます。地味に見づらい。
三項演算子で1つのジョブにまとめることで解決しました:
# After: 実行されるジョブだけ表示
jobs:
deploy:
name: CD (${{ github.ref_name }})
with:
environment: ${{ github.ref_name == 'main' && 'production' || ... }}Vercel Pro プランの制約(Custom Environment は1つまで、Preview の環境変数が固定)を GitHub Actions で回避した構成を紹介しました。
ポイントとしては:
この構成で dev / stg / prd の3環境 + 各環境向けのプレビューデプロイが実現できています。Vercel Pro プランで複数環境を構築したい方の参考になれば幸いです。