0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

GithubActionsで環境変数によってルートディレクトリを切り替えてVercelにデプロイしてみる[Vercel,GithubActions]

Posted at

個人で関わっているプロジェクトで、モノレポでフロントエンドアプリケーションを2つ管理(ver2とver3)しており、vercelで登録しているネームサーバーを使い回しながら最新版のアプリケーションをstagingにvercelにデプロイする必要がありました。

しかし、vercelのGithub連携ではルートディレクトリが1つしか設定できないのに加えて、環境変数ごとにルートディレクトリを切り替えることができないため、CDを回すことが困難でした。

今回はその問題をGithubActionsで解決してみました。

Actionsを組む

トークンを作成する

Vercelで使用するためのアクセストークンを作成します。

image.png

作成したらGithubのリポジトリにsecretsを以下のように設定します。
image.png

ID等を調べる

トークン以外にも2つシークレットに設定する必要があるのでそちらを調査します。

image.png

設定する内容は以下のようになっています。

名前 概要
PROJECT_ID プロジェクトのsettingsにあるID
ORG_ID TeamのsettingsにあるTeamIDのこと

workflowを組んでみる

今回vercelにデプロイするにあたって、ドメインは無料で準備できましたが、vercelで使える環境変数はHobbyプランだと準備できなかったので、ドメインでstgがprdかを区別しようと思います。

環境 ドメイン
production monorepo-deploy-vercel.vercel.app
staging stg-monorepo-deploy-vercel.vercel.app

以下workflowです。

  • prdリリース用
name: deploy
env:
  VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
  VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
on:
  push:
    branches:
      - main

jobs:
  deploy:
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: ./yarn
    steps:
      - name: Checkout code
        uses: actions/checkout@v2
      - name: Set up Node.js
        uses: actions/setup-node@v2
        with:
          node-version: '20'
      - name: Install dependencies
        run: yarn install
      - name: install vercel CLI
        run: yarn global add vercel
      - name: Pull Vercel Environment Information
        run: vercel pull --yes --environment=production --token=${{ secrets.VERCEL_TOKEN }}
      - name: Build Project Artifacts
        run: vercel build --prod --token=${{ secrets.VERCEL_TOKEN }}
      - name: Deploy to Vercel (production)
        id: vercel_deploy
        env:
            VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
        run: |
              output=$(vercel --token $VERCEL_TOKEN)
              echo "$output"
              echo "url=$output" >> $GITHUB_OUTPUT
      - name: set Vercel Alias
        run: |
            vercel alias set ${{ steps.vercel_deploy.outputs.url }} monorepo-deploy-vercel.vercel.app --token=${{ secrets.VERCEL_TOKEN }}
  • stgリリース用
name: deploy-stg.yml
env:
  VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
  VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
on:
  push:
    branches:
      - develop

jobs:
  deploy:
    runs-on: ubuntu-latest
    defaults:
        run:
          working-directory: ./pnpm
    steps:
        - name: Checkout code
          uses: actions/checkout@v2
        - name: Set up Node.js
          uses: actions/setup-node@v2
          with:
            node-version: '20'
        - uses: pnpm/action-setup@v4
          name: Install pnpm
          with:
            version: 10
            run_install: false
        - name: Install vercel CLI
          run: pnpm install -g vercel
        - name: Pull Vercel Environment Information
          run: vercel pull --yes --environment=preview --token=${{ secrets.VERCEL_TOKEN }}
        - name: Build Project Artifacts
          run: vercel build --token=${{ secrets.VERCEL_TOKEN }}
        - name: Deploy to Vercel (preview)
          id: vercel_deploy
          env:
            VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
          run: |
            output=$(vercel --token $VERCEL_TOKEN)
            echo "$output"
            echo "url=$output" >> $GITHUB_OUTPUT
        - name: set Vercel Alias
          run: |
            vercel alias set ${{ steps.vercel_deploy.outputs.url }} stg-monorepo-deploy-vercel.vercel.app --token=${{ secrets.VERCEL_TOKEN }}

outputs

各stepsで実行した内容はsteps.[id].outputs.[key]で参照することができます。

idはstepsで以下のように設定します。

- name: Deploy to Vercel (preview)
  id: vercel_deploy

そこから出力させるために下のように$GITHUB_OUTPUTSを使用します。
下の場合、keyoutput_${version}となります。

 echo "output_${version}=${version}" >> "$GITHUB_OUTPUT"

1つのworkflowsファイルにまとめる

今回のworkflowsとしてはブランチごとに環境変数を設定して使いまわせるような形にしてみます。

インターン先でjsonを使って比較的綺麗に環境変数をまとめて使う方法を教えてもらったのでそちらを使いたいと思います。

workflows作成

deploy-for-vercel.yml
name: deploy-for-vercel.yml
on:
  workflow_call:
    inputs:
      environment:
        required: true
        type: string
env:
  VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
  VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
  ENV_JSON: | #デプロイする環境によって環境変数を変更する。
    ${{ toJson(  
      fromJson('{
        "staging":{
          "PM": "pnpm",
          "DIRECTORY": "./pnpm",
          "VERCEL_ENV": "preview",
          "VERCEL_URL": "stg-monorepo-deploy-vercel.vercel.app"
        },
        "production":{
          "PM": "yarn",
          "DIRECTORY": "./yarn",
          "VERCEL_ENV": "production",
          "VERCEL_URL": "monorepo-deploy-vercel.vercel.app"
        }
      }')[inputs.environment]) }} #inputsでデプロイする環境を入力
jobs:
  deploy:
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: ${{ fromJson(env.ENV_JSON).DIRECTORY }} #Jsonから文字列を取り出す
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
      - name: Set up Node.js
        uses: actions/setup-node@v4
        with:
          node-version-file: ${{ fromJson(env.ENV_JSON).DIRECTORY }}/package.json
      - name: Install pnpm
        if: ${{ fromJson(env.ENV_JSON).DIRECTORY == './pnpm' }}
        uses: pnpm/action-setup@v4
        with:
          version: 10
          run_install: false
      - name: Install dependencies
        run: ${{ fromJson(env.ENV_JSON).PM }} install
      - name: Install vercel CLI
        run: |
          if [ -f yarn.lock ]; then
            yarn global add vercel
          elif [ -f pnpm-lock.yaml ]; then
            pnpm add -g vercel
          fi
      - name: Pull Vercel Environment Information
        run: vercel pull --yes --environment=${{ fromJson(env.ENV_JSON).VERCEL_ENV }} --token=${{ secrets.VERCEL_TOKEN }}
      - name: Build Project Artifacts
        run: vercel build --token=${{ secrets.VERCEL_TOKEN }}
      - name: Deploy to Vercel
        id: vercel_deploy
        env:
          VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
        run: |
          output=$(vercel --token $VERCEL_TOKEN)
          echo "$output"
          echo "url=$output" >> $GITHUB_OUTPUT
      - name: Set Vercel Alias
        run: |
          vercel alias set ${{ steps.vercel_deploy.outputs.url }} ${{ fromJson(env.ENV_JSON).VERCEL_URL }} --token=${{ secrets.VERCEL_TOKEN }}

JSONの使い方

JSONを使うためにactionsで用意されてる関数を使用します。

メソッド 役割
fromJson 文字列をJSONにエンコード
toJson JSONを文字列にデコード

今回の場合は[でkeyを選択することで、ネストされているJSONを取り出しています。

${{ fromJSON(jsonString)[key] }}

そこからtoJsonを使って文字列に変換し、環境変数で設定できるようにしています。

JSONオブジェクトから文字列に変換することをシリアライズと言います。

  ENV_JSON: | #デプロイする環境によって環境変数を変更する。
    ${{ toJson(  
      fromJson('{
        "staging":{
          "PM": "pnpm",
          "DIRECTORY": "./pnpm",
          "VERCEL_ENV": "preview",
          "VERCEL_URL": "stg-monorepo-deploy-vercel.vercel.app"
        },
        "production":{
          "PM": "yarn",
          "DIRECTORY": "./yarn",
          "VERCEL_ENV": "production",
          "VERCEL_URL": "monorepo-deploy-vercel.vercel.app"
        }
      }')[inputs.environment]) }} #inputsでデプロイする環境を入力

workflowを使う

下のようなymlを書くことでworkflowsを使うことができます。

これはtriggerのような役割をして、どのブランチに対してpushやPRなどの特定の操作を行ったら、workflowsをどのような環境で使用するかを指定するかを定義できます。

deploy-stg.yml
name: deploy-stg.yml
on:
  push:
    branches:
      - develop

jobs:
  deploy:
    uses: ./.github/workflows/deploy-for-vercel.yml
    secrets: inherit #secretsを引き継ぐことができる
    with:
      environment: staging

workflowファイルはjobsでしか呼び出せないため、stepsには書かず、jobsに書いています。

また、workflowsにsecretsの情報を引き継ぐためにsecrets: inheritを記述しています。

最後に

結局、組織アカウントのプライベートリポジトリはGithubEnterprise等の課金をしてないとsecretsが使えないため上のやり方は断念しました。

チキショー

ただ、jsonの使い方は面白く使えるところが多いと思うのでぜひ参考にしてみてください。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?