🖖

Cloud SQL + Prisma のマイグレーションを GitHub Actions で実行する

2022/08/30に公開

Cloud SQL + Prisma な環境で GitHub Actions からマイグレーションを実行する方法の紹介です
App Engine や Cloud Run など、ソケット接続が前提のサービスへデプロイすることを一応想定していますがしていますがそうでない場合でも使えます

Cloud SQL への接続方法

Cloud SQL への接続は TCP 接続とソケット接続の2通りがありますが、今回はソケット接続で行っていきます

アプリケーションを App Engine や Cloud Run などへデプロイする場合は Cloud SQL に Unix ソケット経由で接続することになります(パブリック IP の場合)
そのため、アプリケーションから Cloud SQL へソケット接続するための Connection URL (接続情報)を秘密情報として持っておく必要がありますが、マイグレーションを TCP 接続でやってしまうと TCP 接続用の Connection URL を別途用意しなければいけません

App Engine や Cloud Run のように、実行時にソケット接続するような環境の場合はマイグレーションもソケット接続で行うことで秘密情報となる Connection URL が一つだけで済むのでオススメです

Connection URL

Prisma のスキーマファイルでは以下のように Connection URL を環境変数から引っ張ってくることを想定しています

datasource db {
  provider = "mysql"
  url      = env("CONNECTION_URL")
}

GitHub Actions ワークフロー

実際のワークフローがこちらです(重要な部分以外省略しています)

jobs:
  migration:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Start Cloud SQL Auth Proxy
        run: |
          wget https://dl.google.com/cloudsql/cloud_sql_proxy.linux.amd64 -O cloud_sql_proxy
          chmod +x cloud_sql_proxy
          mkdir /tmp/cloudsql
          ./cloud_sql_proxy -dir=/tmp/cloudsql -instances=<INSTANCE_CONNECTION_NAME> -credential_file=<CREDS_PATH> &

      - name: Database migration
        run: CONNECTION_URL=${CONNECTION_URL//\/cloudsql/\/tmp\/cloudsql} npx prisma migrate deploy
変数 説明
<INSTANCE_CONNECTION_NAME> インスタンス接続名。 <project id>:<region>:<db name> 形式の文字列です。Cloud SQL のコンソールから確認できます
<CREDS_PATH> サービスアカウント JSON ファイルが置いてあるパスです

環境変数 CONNECTION_URL には先程紹介した Connection URL を入れておきます
App Engine / Cloud Run からの利用を想定する場合、 /cloudsql 以下にソケットが作成されるので次のような Connection URL になると思います

mysql://user:password@localhost/db_name?socket=/cloudsql/INSTANCE_CONNECTION_NAME

各ステップ(といっても2つしかないですが)を順に解説していきます

Cloud SQL Auth Proxy を立ち上げる

      - name: Start Cloud SQL Auth Proxy
        run: |
          wget https://dl.google.com/cloudsql/cloud_sql_proxy.linux.amd64 -O cloud_sql_proxy
          chmod +x cloud_sql_proxy
          mkdir /tmp/cloudsql
          ./cloud_sql_proxy -dir=/tmp/cloudsql -instances=<INSTANCE_CONNECTION_NAME> -credential_file=<CREDS_PATH> &

Cloud SQL Auth Proxy をダウンロードして立ち上げています
ソケットを生成するパスを指定する -dir パラメータは App Engine / Cloud Run 上での環境と合わせて /cloudsql としたいところですが、 runs-on: ubuntu-latest 環境では Permission denied となってしまうので /tmp/cloudsql を作成し、指定しています

./cloud_sql_proxy 実行部の最後の & をつけてバックグラウンド実行しないとワークフローがスタックしてしまうので注意です

マイグレーションを実行する

      - name: Database migration
        run: CONNECTION_URL=${CONNECTION_URL//\/cloudsql/\/tmp\/cloudsql} npx prisma migrate deploy

ここは prisma migrate deploy を実行しているだけですが、 CONNECTION_URL=${CONNECTION_URL//\/cloudsql/\/tmp\/cloudsql} が肝になります

先程のステップで /tmp/cloudsql 以下にソケットを作成していますが、接続情報のソケット指定部は App Engine / Cloud Run 向けに合わせて socket=/cloudsql/INSTANCE_CONNECTION_NAME となっているため、マイグレーション実行時のみ環境変数内のパスを置換して /tmp/cloudsql へ向くようにしています

まとめ

  • App Engine / Cloud Run にデプロイするならソケット接続してマイグレーション走らせたほうが秘密情報1つで済むのでおすすめ

意外とハマったので参考になれば幸いです😊

参考

Discussion