はじめに
こんにちは! 株式会社インダストリー・ワンのエンジニア、角田です。
インダストリー・ワンでは、クライアントのサービス開発以外にも様々な取り組みを行っていますが、その中の一つにプロダクトのベースとして使うための、スターターキットの開発があります。
今回はその中で私が担当した、GitHub Actions で Prisma の DB マイグレーションを実行するようにした改善について、試行錯誤の中で得られた知見を共有したいと思います。
開発環境(一部)
前提として、以下のツールを用いて開発しています。
- BackEnd:NestJS
- DB:postgresql
- ORM:prisma
背景・目的
本プロジェクトでは GitHub Actions を使って、CI/CD を行っています。
今回説明したいポイントに絞ると、以下の流れとなっています。
As Is
flowchart TD A(マイグレーションファイル\n作成) --> B(GitHubへpush) B --> C(デプロイ開始) C --> D(本番環境\nマイグレーション\n実行) D --> E{成否} E --> |成功| F(サービス起動) E --> |失敗| G(サービス起動失敗)
この場合、デプロイ開始後に本番環境でマイグレーション実行しているため、マイグレーション時のエラーが存在してもデプロイでき、サービス起動失敗してしまう問題がありました。
そのため以下のように変更し、GitHub Actions でテスト用マイグレーションを追加したいと考えました。
To Be
flowchart TD A(マイグレーションファイル\n作成) --> B(GitHubへpush) B --> C(テスト用マイグレーション) C --> D{成否} D -->|成功| E(デプロイ開始) D -->|失敗| F(デプロイ中止) E --> G(本番環境\nマイグレーション\n実行) G --> H(サービス起動)
こうすることでデプロイ開始前にマイグレーションの成否確認ができ、
マイグレーションのエラー時は、デプロイを中止させることができるという狙いです。
成果物
作成した GitHub Actions の設定ファイルがこちらになります。
ここに定義したテスト用マイグレーションの処理を push 時に行います。
.github/workflows/migration_test.yml
name: Migration test # 既存のメインActionから呼び出し実行する on: workflow_call: # 環境変数に postgresql の接続文字列を定義(schema.prismaでDBに接続するときに使う) env: DB_USER: postgres DB_PASSWORD: passw0rd DB_HOST: localhost DB_PORT: 5432 DB_NAME: postgres DB_SCHEMA: public DATABASE_URL: postgresql://${DB_USER}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_NAME}?schema=${DB_SCHEMA} jobs: migration_test: runs-on: ubuntu-latest # サービスコンテナを利用しpostgresqlを使えるように設定 services: postgres: image: postgres env: POSTGRES_PASSWORD: passw0rd # Set health checks to wait until postgres has started options: >- --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 ports: # tcp port 5432をサービスコンテナ→ホストにマッピング - 5432:5432 # GitHub Actionsの実行 steps: - name: Check out repository code uses: actions/checkout@v3 - name: install pnpm run: npm install -g pnpm@7.25.1 - name: install packages run: pnpm install - name: Run Migration run: pnpm --filter=<マイグレーションファイルがあるパッケージ> prisma migrate deploy
ハマった箇所
筆者の知見不足もあり、上記の完成系に持っていくには色々と試行錯誤がありました。
その中で、自身の備忘録も兼ねて、得られた知見を共有いたします。
ちなみに筆者の事前理解としては、こんなレベルでした。
得られた知見としては、以下のようなものがありました。
GitHub Actionsを動かすには
詳細
プロジェクトルートに、.github/workflows/フォルダ配下にymlファイルがあれば動かすことができます。
yml内部のon:に、実行するタイミングを記載すれば、そのタイミングでjob:に記載されたジョブが実行されます。
成果物 では、"workflow_call:"を指定しており、既存のメインActionとなるymlから呼び出すようにしています。 メインymlの詳細は割愛しますが、on:に"push:"を指定しており、プッシュ時に実行されるようになっています。
GitHub Actionsの詳細は公式ページ参照。
docs.github.com
GitHub Actionsでコンテナを使いたい場合、サービスコンテナを使うと吉
詳細
マイグレーションを行うために、一時的なDB環境が必要であり、それを構築するためのコンテナが必要でした。
GitHubは、サービスコンテナという、コンテナを作成できる機能を持っています。これを使えば自前でコンテナの作成コマンドを打つ必要がありません。
(私はそれを知らず、最初ワークフローの中でdocker-compose up
を実行して、Dockerコンテナを作ろうとしていました。。(汗)
docs.github.com
サービスコンテナの接続文字列のデフォルト値
詳細
成果物
のenv:で接続文字列を指定していますが、最初はこれらを何に指定すれば良いか、分かりませんでした。
以下のJavaScriptコードの例で接続文字列を指定しているのですが、なぜそのように決まるか疑問でした。
docs.github.com
postgresのDockerイメージを確認したところ、以下のようにデフォルト値が決まっていました。
- ユーザ名(POSTGRES_USER):postgres
- DB名(POSTGRES_DB):POSTGRES_USERの値
ユーザーが必須で指定しなければいけないのは、POSTGRES_PASSWORDのみということでした。
hub.docker.com
またホスト名ですが、ランナーマシン上でジョブを直接実行する場合、"localhost"か "127.0.0.1"を使ってサービスコンテナにアクセスできます。
docs.github.com
結果的に、以下のように決まります。
- ユーザ名:postgres
- DB名:postgres
- ホスト名:localhost
それ以外のパスワードとポート番号は、 成果物 にて、以下のように記載しています。
jobs: migration_test: ... services: postgres: image: postgres env: POSTGRES_PASSWORD: passw0rd ... ports: # tcp port 5432をサービスコンテナ→ホストにマッピング - 5432:5432
prismaのマイグレーションの流れ
詳細
ご存知の方には言わずもがなですが、大まかに以下の流れとなります。
.envファイルの用途
詳細
schema.prisma を作成する場所に.env ファイルがあれば、内部に定義されている文字列を、環境変数として扱ってくれます。
今回のケースでは、既にローカルで動かすための.env ファイルが存在していたため、.env ファイルではなく
成果物
の env:で環境変数を指定する形をとりました。
.env ファイルの記載例:
env: DB_USER: postgres DB_PASSWORD: passw0rd DB_HOST: localhost DB_PORT: 5432 DB_NAME: postgres DB_SCHEMA: public DATABASE_URL: postgresql://${DB_USER}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_NAME}?schema=${DB_SCHEMA}
.env以外のファイルを使用して環境変数を設定するには
詳細
を使用します。 以下は、.env の代わりに.env.migration_test を使用する例です。
dotenv -e .env.migration_test -- prisma migrate deploy
GitHub Actions のワークフローで使用する場合は、以下のようにインストール処理が必要です。
run: pnpm add -w dotenv-cli
今回は最終的に使いませんでしたが、ローカルで使用する.env とは異なるファイルを使いマイグレーションを行うことも検討していました。その中で得られた知見でした。
www.prisma.io
.envファイルに記載された環境変数を使わないようにするには
詳細
GitHub Actions の yml ファイルに、"env:"を記載しておけば、そちらが優先して使用されます。
まとめ
今回は GitHub Actions で Prisma マイグレーション実行の設定をする中で、得られた知見を共有させていただきました。
こういった知見がない分野で試行錯誤しながら実施することは、大変な一面がありましたが、経験豊富なメンバーから助言をもらいながら進めることができました。結果的に自身の成長につながったと思います!
以上、最後まで読んでくださり、ありがとうございました。
おわりに
インダストリー・ワンでは一緒に働く仲間を募集しています。
少しでも興味を持っていただいた方は、是非以下から応募していただければと思います。もちろんカジュアル面談からでも OK!
どうぞ宜しくお願いいたします。