DB スキーマのマイグレーションをオブジェクトストレージ経由で行う dbmate-deployer を作った

https://github.com/tokuhirom/dbmate-deployer

やりたいこととしては、以下の通り。

という構成の場合に、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