DB スキーマのマイグレーションをオブジェクトストレージ経由で行う dbmate-deployer を作った
https://github.com/tokuhirom/dbmate-deployer
やりたいこととしては、以下の通り。
- DB の schema migration をサーバーにログインせずに行いたい。
- github actions からは DB に直接アクセスしたくない
- github actions からオブジェクトストレージにはアクセス可能
- スキーマ適用の履歴が残って欲しい
という構成の場合に、github actions からオブジェクトストレージにスキーママイグレーションスクリプトをアップすることをきっかけにマイグレーションが走る仕組みを作った。
構成としては以下のようになっていて、YYYYMMDDHHMMSS なディレクトリに migration script を sync すると、dbmate-deployer の常駐プロセスが polling してくれていて適用してくれる。結果は result.json というファイルに書き込まれる。
s3://your-bucket/${S3_PATH_PREFIX}/
20260121010000/ # Version: YYYYMMDDHHMMSS
migrations/ # Migration SQL files (directory name is fixed)
20260101000000_create_users.sql
20260102000000_add_email.sql
result.json # Execution result (created after run)
20260121020000/ # Newer version
migrations/ # Directory name "migrations/" is fixed and cannot be changed
20260101000000_create_users.sql # Previous migrations included
20260102000000_add_email.sql # Previous migrations included
20260103000000_add_posts.sql # New migration
# No result.json = unapplied version
github actions には以下のように書けば良い。
name: Upload Migrations
on:
workflow_dispatch:
jobs:
upload:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Generate migration version
run: |
VERSION=$(date -u +%Y%m%d%H%M%S)
echo "MIGRATION_VERSION=$VERSION" >> $GITHUB_ENV
echo "Generated version: $VERSION"
- name: Download dbmate-deployer
run: |
curl -LO https://github.com/tokuhirom/dbmate-deployer/releases/latest/download/dbmate-deployer_linux_amd64.tar.gz
tar -xzf dbmate-deployer_linux_amd64.tar.gz
chmod +x dbmate-deployer
- name: Upload migrations to S3
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
S3_ENDPOINT_URL: ${{ secrets.S3_ENDPOINT_URL }}
S3_BUCKET: ${{ secrets.S3_BUCKET }}
S3_PATH_PREFIX: ${{ secrets.S3_PATH_PREFIX }}
run: |
./dbmate-deployer push \
--migrations-dir=db/migrations \
--version=${{ env.MIGRATION_VERSION }}
- name: Wait for completion and notify
if: always()
env:
S3_BUCKET: ${{ secrets.S3_BUCKET }}
S3_PATH_PREFIX: ${{ secrets.S3_PATH_PREFIX }}
S3_ENDPOINT_URL: ${{ secrets.S3_ENDPOINT_URL }}
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
SLACK_INCOMING_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }}
run: |
./dbmate-deployer wait-and-notify --migration-version=${{ env.MIGRATION_VERSION }}
dbmate-deployer push でオブジェクトストレージにアップしている。
dbmate-deployer wait-and-notify で result.json がアップされるのを待つ。result.json が成功状態だったら action は成功するし、失敗してればエラーになる。SLACK_INCOMING_WEBHOOK という環境変数があれば、良い感じに成否が通知されるという感じ。
設定簡単でお手軽なのでご利用ください。
Published: 2026-01-23(Fri) 23:57