【Hasura】DBのマイグレーションをGit管理してGitHub Actionsで自動デプロイする方法 with Docker
はじめに
HasuraではDocker Composeを使用してローカル環境を構築できます。
Hasuraコンソール上での各種操作はマイグレーションファイル、メタデータとしてファイル生成されます。
.
└── hasura
├── config.yaml
├── metadata
│ ├── actions.graphql
│ ├── actions.yaml
│ ├── allow_list.yaml
│ ├── api_limits.yaml
│ ├── backend_configs.yaml
│ ├── cron_triggers.yaml
│ ├── databases
│ │ ├── databases.yaml
│ │ └── default
│ ├── graphql_schema_introspection.yaml
│ ├── inherited_roles.yaml
│ ├── metrics_config.yaml
│ ├── network.yaml
│ ├── opentelemetry.yaml
│ ├── query_collections.yaml
│ ├── remote_schemas.yaml
│ ├── rest_endpoints.yaml
│ └── version.yaml
├── migrations
│ └── default
│ ├── 1675684572606_init
│ ├── 1675709384448_create_table_public_articles
│ └── 1675712066438_create_table_public_article_categories
└── seeds
└── default
└── 1675712324456_init_article_category.sql
今回はそこで生成されたメタデータをGit管理し、GitHub Actionsで自動デプロイを行います。
公式がGitHubリポジトリとの連携機能を提供しているためGitHub Actionsを使用しなくても実現可能です。
今回は他のジョブとの実行順序をコントロールする(例:Hasuraの変更後にフロントエンドをデプロイ)ことを想定してGitHub Actionsを使用します。
必要なもの
- Hasuraアカウント
- Hasura CLI
- Docker Compose
やってみる
1. Hasuraプロジェクトの準備
こちらからプロジェクトを作成。
DBの接続設定をします。
Neonは1プロジェクトのみ無料でDBを作成できます。
2. GitHubリポジトリを作成
フリーアカウントの場合はパブリックで作成してください。
どうしてもプライベートで作成したい場合は、次の手順でEnvironmentではなくSecretsを使用してください。
3. リポジトリに本番環境用のEnvironmentを用意
GitHub Environmentsとは環境ごとに環境変数を作成する機能です。
ステージング環境と本番環境それぞれで環境変数を設定したいときなどに便利です。
今回は本番環境のみ作成するのでこちらをあえて使用する必要はありませんが、今後追加の環境を作成することを想定してこちらを採用します。
注意:フリーアカウントのプライベートリポジトリでは使用できません。
参照:Using environments for deployment
HasuraコンソールからHASURA_ADMIN_SECRET
とHASURA_ENDPOINT
を取得します。
HASURA_ENDPOINT
は「GraphQL API」のドメイン名まで(https://<project name>.hasura.app
)です。
Environment名はproduction
で作成します。
https://github.com/<username>/<repository name>/settings/environments
4. ローカル環境をセットアップ
git clone <repository url>
cd <repository url>
hasura init
.
└── hasura
├── config.yaml
├── metadata
├── migrations
└── seeds
ルートディレクトリ直下にdocker-compose.yml
を作成します。
version: '3.6'
services:
postgres:
image: postgres:15
restart: always
volumes:
- db-data:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: postgrespassword
graphql-engine:
image: hasura/graphql-engine:v2.17.0
ports:
- "8080:8080"
depends_on:
- "postgres"
restart: always
environment:
HASURA_GRAPHQL_METADATA_DATABASE_URL: postgres://postgres:postgrespassword@postgres:5432/postgres
PG_DATABASE_URL: postgres://postgres:postgrespassword@postgres:5432/postgres
HASURA_GRAPHQL_ENABLE_CONSOLE: "true"
HASURA_GRAPHQL_DEV_MODE: "true"
HASURA_GRAPHQL_ENABLED_LOG_TYPES: startup, http-log, webhook-log, websocket-log, query-log
volumes:
db-data:
コンテナを起動。
docker-compose up --build
5. HasuraからDBに接続
cd hasura
hasura console
INFO console running at: http://localhost:9695/
DATAタブからDBの接続情報を設定します。
Database Display Nameをdefault
に、Environment VariableをPG_DATABASE_URL
にします。
6. テーブルを追加
DATAタブから適当にテーブルを作成してください。
テーブル作成に合わせてマイグレーションファイルが作成されていることがわかります。
hasura/migrations
└── default
└── 1675775890486_create_table_public_users
├── down.sql
└── up.sql
7. GitHub Actionsのワークフローを作成
main
ブランチにPushされた際、migration・metadata・seedの変更を反映します。
以下ワークフローを作成します。
.github/workflows/deploy.yml
name: deploy
on:
push:
branches:
- main
paths:
- 'hasura/**'
jobs:
deployment:
environment: production
runs-on: ubuntu-latest
steps:
- name: checkout repo
uses: actions/checkout@v3
- name: apply hasura migrations
uses: tibotiber/hasura-action@v3.0
with:
args: migrate apply --all-databases
env:
HASURA_ENDPOINT: ${{ secrets.HASURA_ENDPOINT }}
HASURA_ADMIN_SECRET: ${{ secrets.HASURA_ADMIN_SECRET }}
HASURA_WORKDIR: hasura
HASURA_ENGINE_VERSION: v2.17.1
- name: apply hasura seed
uses: tibotiber/hasura-action@v3.0
with:
args: seed apply --all-databases
env:
HASURA_ENDPOINT: ${{ secrets.HASURA_ENDPOINT }}
HASURA_ADMIN_SECRET: ${{ secrets.HASURA_ADMIN_SECRET }}
HASURA_WORKDIR: hasura
- name: apply hasura metadata
uses: tibotiber/hasura-action@v3.0
with:
args: metadata apply
env:
HASURA_ENDPOINT: ${{ secrets.HASURA_ENDPOINT }}
HASURA_ADMIN_SECRET: ${{ secrets.HASURA_ADMIN_SECRET }}
HASURA_WORKDIR: hasura
HASURA_ENGINE_VERSION: v2.17.1
GitHub Environment名をproduction
以外で作成した場合は、以下の箇所を修正してください。
jobs:
deployment:
environment: production
今回はテーブル追加しか行っていないため、metadataとseedの反映は不要ですが今後のために追加してあります。
8. Commit and Push
git add -A
git commit -m "add new table"
git push origin main
9. 確認
Hasuraコンソールからテーブルが正常に作成されていることを確認します。
エラーが表示されている場合はGitHub Actionsのログを確認してください。
Hints
既存プロジェクトをGit管理する
ローカルでHasuraプロジェクトを生成する際に、すでに作成済みのプロジェクトからエクスポート可能です。
hasura init <directory name> --endpoint <endpoint URL> --admin-secret <admin secretkey>
この方法で作成した場合、設定ファイルに本番環境のエンドポイントURLとシークレットが設定されます。
hasura/config.yaml
version: 3
endpoint: <endpoint URL>
admin_secret: <admin secret>
metadata_directory: metadata
actions:
kind: synchronous
handler_webhook_baseurl: http://localhost:3000
このままコンテナを起動すると本番環境に向いてしまうため、以下のように修正してください。
version: 3
endpoint: http://localhost:8080
metadata_directory: metadata
actions:
kind: synchronous
handler_webhook_baseurl: http://localhost:3000
シードデータを作成する
方法①:SQLファイルを手動生成
hasura seed create <seed name>
方法②:ローカル環境のテーブルのレコードから生成
ローカル環境のテーブルのデータをそのまま使用したい場合は--from-table
オプションを使用します。
hasura seed create <seed name> --from-table <table name>
プレビューアプリの作成
ベータ版ですがPRごとにプレビュー用のアプリを作成できます。
ただし使用するDBはこちらで用意する必要があります。
やっていることはざっくりとこんな感じです。
- プレビュー用のDB URLを複数設定
- PR作成時にHasuraプロジェクトが自動生成される
- 設定されたDB URLが自動で割り当てられる
- PRマージorクローズ時にアプリを削除
PRごとにDBが必要になります。
プレビューのために複数個DBを用意する必要があるため、あまり現実的はないですね。
またエンドポイントURLとシークレットは動的なため、フロントエンドのプレビュー用アプリと接続する際には注意が必要です。
message: |
Console URL available at ${{steps.hasura_cloud_preview.outputs.consoleURL}}
GraphQL Endpoint available at ${{steps.hasura_cloud_preview.outputs.graphQLEndpoint}}
フロントエンドのデプロイ先にGitHub Actionsから環境変数を設定する方法があれば自動で連携できそうですが、そうでない場合は手動で設定が必要です。
おわりに
Git管理と自動デプロイができたところでやっと開発スタートです。
Discussion