CircleCIでvercelにデプロイする(2021年版)

vercel, CircleCI, deploy
2021-11-01

CircleCIを利用してGitHubのpushから自動的にvercelのプロジェクトへデプロイする方法です。2019年頃、まだvercelがnowだった時代にやっていたのですがいろいろ変わったので再度設定してみました。

TL;DR;

自分の場合はCircleCIのconfigファイルを以下のように設定し、GitHubにpushすることで自動的にデプロイが実行されます。

version: 2.1

orbs:
  node: circleci/node@4.7

jobs:
  checkout:
    executor: node/default
    working_directory: ~/tmp/project-frontend
    steps:
      - checkout
      # Download and cache dependencies
      - node/install-packages
      # 次のdeployをするためにディレクトリを永続化
      - persist_to_workspace:
          root: .
          paths:
            - .
  deploy:
    executor: node/default
    working_directory: ~/tmp/project-frontend
    steps:
      - attach_workspace:
          at: ~/tmp/project-frontend # 前のjobの成果物をダウンロード
      - run:
          name: Install Vercel CLI
          command: sudo npm install --global vercel
      - deploy:
          name: Deploy & Alias
          command: |
            if [ "${CIRCLE_BRANCH}" == "staging" ]; then
              DEPLOYMENT_URL=$(vercel -S your_team -t $VC_TOKEN --confirm -A ./vercel.json)
              vercel -S your_team -t $VC_TOKEN alias set $DEPLOYMENT_URL staging.project.com
            elif [ "${CIRCLE_BRANCH}" == "production" ]; then
              DEPLOYMENT_URL=$(vercel -S your_team -t $VC_TOKEN --confirm -A ./vercel.json --prod)
            fi

# Invoke jobs via workflows
workflows:
  deploy-to-stage:
    jobs:
      - checkout:
          filters:
            branches:
              only:
                - staging
      - deploy:
          requires:
            - checkout
          filters:
            branches:
              only:
                - staging
  ...

以下、解説

下準備

vercelのプロジェクトを作成

予めvercel上のプロジェクトを作成しておきます。

ローカルでvercelコマンド実行することで、vercel上にプロジェクトを作成、デプロイできるので、事前に行います

vercelコマンドの詳細はこちらを確認ください

CircleCIの登録

CircleCIへサインアップまたはサインインし、デプロイ対象であるリポジトリを登録します。

アクセストークンの設定

CircleCIからvercelにアクセスするため、vercelのアクセストークンが必要になるため、vercelのサイト上のPersonal Account Settings > Tokens から新しいトークンを生成します。 生成した、トークンをCircleCIのProject SettingsのEnvironment Variableから追加します。

An image from Notion
CircleCIにトークンを設定

設定したトークンは(この例だと) $VC_TOKEN でアクセスできます。

Configについて

今回はCircleCIのv2.1を利用します。v2.1からCircleCIではOrbと呼ばれるビルドの設定を個別のパッケージにし、再利用できる仕組みが利用できます。

https://circleci.com/orbs/

vercelのプロジェクトでは主にNode.jsを利用するのでオフィシャルのnodeのOrbを利用します。

これによりdockerの設定を自前で書かなくてもよくなり、 node/install-packages を利用することによってnpm ciとインストールしたパッケージを自動的にキャッシュ(キャッシュ先はデフォルトで '~/.npm' )してくれます。

https://circleci.com/developer/orbs/orb/circleci/node

version: 2.1

orbs:
  node: circleci/node@4.7

jobsの設定

jobsは2つ登録します

  • checkout
    • working_directoryのディレクトリ名はvercelのプロジェクト名と同じにします。
      • vercel の —name オプションで指定してもよいが、現状はdeprecatedなのであまり利用したくはない
      • circleCIのworkspaceディレクトリ上に.vercel/project.jsonを作成するという方法もあるが、煩雑になるのとセキュアなのかもわからないので、この方法も一旦パスしました。
    • githubからソースコードをダウンロードし、パッケージのインストールを行います
    • persist_to_workspace で続くdeployにファイル(npmでinstallしたもの)を渡すため、ディレクトリを永続化します
jobs:
  checkout:
    executor: node/default
    working_directory: ~/tmp/project-frontend
    steps:
      - checkout
      # Download and cache dependencies
      - node/install-packages
      # 次のdeployをするためにディレクトリを永続化
      - persist_to_workspace:
          root: .
          paths:
            - .
  • deploy
    • vercel cli を利用してvercelの環境にデプロイを行います。
      • 今回は stagingブランチをvercelのpreviewモードとし、stagingのサブドメインでアクセスし、 prodution モードを本番とて運用にすることを想定します
      • shell上で DEPLOYMENT_URL=$(vercel ...) のようにvercelコマンドの戻り値がvercelのdeploymentのURL(eg. porject-frontend-5rz1qnta0-ahdee.vercel.app )となるので、そのURLに対し、aliasでURLを当てることにより、最新のdeploymentがstagingのURLに向くようにします
      • 本番(productionモード)では自動的にURLが割り当てられるため、設定は特にしていません
    • attach_workspaceで前述のcheckoutで生成したものをダウンロードし展開します。
  deploy:
    executor: node/default
    working_directory: ~/tmp/project-frontend
    steps:
      - attach_workspace:
          at: ~/tmp/project-frontend # 前のjobの成果物をダウンロード
      - run:
          name: Install Vercel CLI
          command: sudo npm install --global vercel
      - deploy:
          name: Deploy & Alias
          command: |
            if [ "${CIRCLE_BRANCH}" == "staging" ]; then
              DEPLOYMENT_URL=$(vercel -S your_team -t $VC_TOKEN --confirm -A ./vercel.json)
              vercel -S your_team -t $VC_TOKEN alias set $DEPLOYMENT_URL staging.project.com
            elif [ "${CIRCLE_BRANCH}" == "production" ]; then
              DEPLOYMENT_URL=$(vercel -S your_team -t $VC_TOKEN --confirm -A ./vercel.json --prod)
            fi

workflow

jobの設定が済んだら、それらを動かすworkflowを設定します。workflowはstagingブランチ、productionブランチでjobのcheckout, deployを実行するだけです。

ブランチ毎で分けたいので以下のような設定になります。

# Invoke jobs via workflows
workflows:
  deploy-to-stage:
    jobs:
      - checkout:
          filters:
            branches:
              only:
                - staging
      - deploy:
          requires:
            - checkout
          filters:
            branches:
              only:
                - staging
  deploy-to-prod:
    jobs:
      - checkout:
          filters:
            branches:
              only:
                - production
      - deploy:
          requires:
            - checkout
          filters:
            branches:
              only:
                - production

これでGitHubへpushすると以下のようにstagingブランチでは deploy-to-stageが、productionブランチではdeploy-to-prodが動作します。またmainブランチの場合は対応するworkflowがないためなにも起きません。

An image from Notion

以上になります。

テストの自動実行やslackの通知なども追加できたらいいなと思います。

参考

Written by Kyohei Tsukuda who lives and works in Tokyo 🇯🇵 , building useful things 🔧.