Tech Racho エンジニアの「?」を「!」に。
  • Ruby / Rails以外の開発一般

GitHub ActionsにVercelのGitHub連携っぽいことをやらせてみる

🔗 はじめに

趣味のプロジェクトでホスティングサービスのVercelを使っています。
Vercelにはプルリクエストを立てると、いい感じのプレビュー環境を構築してくれるGitHub連携機能があるんですが、
その周辺の設定がいまいち痒いところに手が届かないというか分かりづらいので、練習がてらGitHub Actionsで管理してみることにしました。

🔗 Vercel側の設定

まず、mainブランチ向けのプルリクエストを作成/更新したときだけプレビュー環境を作り、それ以外何もしないようにしたいので、
Vercel向け設定ファイルのvercel.jsonを以下のようにして完全に自動デプロイを止めます。

{
  "git": {
    "deploymentEnabled": false
  }
}

ちょっと注意なのはgit.deploymentEnabledは完全に止めるかdenylist的な指定しかできないっぽいので、本番環境へのデプロイは生かしたい場合はVercel管理画面のSetting>Git>Ignored Build Stepから設定する必要があります。
(似たような設定をいろんなところでできるのが紛らわしい...)

🔗 作ったワークフロー

これが最終的にできたワークフローです。
普段シェルで小難しいことやらないチンパンなのでそこは勘弁してあげてください。

name: Vercel Preview Deployment
env:
  VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
  VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
on:
  pull_request:
    types: [opened, synchronize]
    branches:
      - main
jobs:
  deploy_preview:
    runs-on: ubuntu-latest
    steps:
      - name: Create Deployment
        id: create_deployment
        uses: octokit/request-action@v2.x
        with:
          route: POST /repos/{owner}/{repo}/deployments
          owner: ${{ github.repository_owner }}
          repo: ${{ github.event.repository.name }}
          ref: ${{ github.head_ref }}
          environment: preview
          required_contexts: '[]'
          auto_merge: false
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      - name: Checkout Code
        uses: actions/checkout@v2
        with:
          ref: ${{ github.head_ref }}
      - name: Install Vercel CLI
        run: npm install --global vercel@latest
      - name: Deploy Project to Vercel
        id: deployment_to_vercel
        run: | 
          set +e
          preview_url=$(vercel deploy --token=${{ secrets.VERCEL_TOKEN }})
          echo "deploy_exit_code=$?" >> $GITHUB_OUTPUT
          set -e
          echo "preview_url=${preview_url}" >> $GITHUB_OUTPUT
      - name: Update Deployment Status
        uses: octokit/request-action@v2.x
        with:
          route: POST /repos/{owner}/{repo}/deployments/{deployment_id}/statuses
          owner: ${{ github.repository_owner }}
          repo: ${{ github.event.repository.name }}
          deployment_id: ${{ fromJson(steps.create_deployment.outputs.data).id }}
          state: ${{ steps.deployment_to_vercel.outputs.deploy_exit_code == 0 && 'success' || 'failure' }}
          environment_url: ${{ steps.deployment_to_vercel.outputs.preview_url }}
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      - name: Promote Error
        run: exit ${{ steps.deployment_to_vercel.outputs.deploy_exit_code }}

VERCEL_TOKENはVercelアカウント設定画面のTokensから発行できて、
VERCEL_ORG_ID, VERCEL_PROJECT_ID はローカル環境でVercel CLIでリンクした際に出来る.vercel/project.jsonに書いてあります(参考)

🔗 困ったりしたところ

🔗 GitHub Deployment

プルリクエストの下の方に出てくるThis branch has not been deployed等のデプロイ状況の表示はVercelみたいなPaaSに連携すると勝手に変わってくれますが、
実際何を根拠に出力されているか分からなくてモタモタしました。
これはGitHub DeploymentをAPIで更新していけば同期してくれるみたいです。
今回のワークフローだとCreate Deploymentステップで作成してUpdate Deployment Statusステップで結果に応じてsuccess, failureに遷移させています。

🔗 コマンドの出力と終了コードをDeploymentに反映させたい

Deploy Project to Vercelステップで実行しているvercel deployコマンドは、
デプロイが成功した場合はプレビュー環境のURL、失敗した場合はビルドログのURLを標準出力するので成否に関わらず保持したかったんですよね。
それで無理やり頑張った結果こんな感じになりました。

- name: Deploy Project to Vercel
    id: deployment_to_vercel
    run: | 
      set +e # vercel deployのエラーで止まらないようにする
      preview_url=$(vercel deploy --token=${{ secrets.VERCEL_TOKEN }}) # URLを退避
      echo "deploy_exit_code=$?" >> $GITHUB_OUTPUT # 終了コードを出力に設定
      set -e # 一応エラーで止まるように戻す
      echo "preview_url=${preview_url}" >> $GITHUB_OUTPUT # URLを出力に設定

保持した終了コードはDeploymentのステータスに使う他、Promote Errorステップをそのままのコードで終了させることでワークフローの成否に反映させてます。

🔗 おわりに

私のシェルちからが足りないせいで汚くなった感じがあり大変辛いですが、ワークフローは今日も元気に動いてくれています。
最後までお読みいただきありがとうございました。



CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。