From c99626e5def0e074409d905ca314c0c26e34cea8 Mon Sep 17 00:00:00 2001 From: wangdl Date: Thu, 18 Jun 2026 14:02:48 +0800 Subject: [PATCH] ci: add database migration automation workflow (API-AI-079) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 3-stage: validate → dry-run → deploy-migration - validate: prisma format check, client generation verification - dry-run: MySQL service container, db push + migrate deploy + status - deploy-migration: manual trigger, SSH migrate deploy with pre/post status - Triggered on schema.prisma or migrations/** changes Co-Authored-By: Claude Opus 4.7 --- .github/workflows/migration.yml | 138 ++++++++++++++++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 .github/workflows/migration.yml diff --git a/.github/workflows/migration.yml b/.github/workflows/migration.yml new file mode 100644 index 0000000..e14c12e --- /dev/null +++ b/.github/workflows/migration.yml @@ -0,0 +1,138 @@ +name: Database Migration + +on: + push: + paths: + - 'prisma/schema.prisma' + - 'prisma/migrations/**' + branches: [main, develop] + pull_request: + paths: + - 'prisma/schema.prisma' + - 'prisma/migrations/**' + workflow_dispatch: + inputs: + run_deploy: + description: 'Run deploy migration against staging DB' + type: boolean + default: false + +env: + NODE_VERSION: '22' + +jobs: + # ═══════════════════════════════════════════════════════════════ + # 1. Validate schema + migration consistency + # ═══════════════════════════════════════════════════════════════ + + validate: + name: Validate Schema + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + cache: 'npm' + - run: npm ci + - run: npx prisma generate + env: + DATABASE_URL: ${{ secrets.MIGRATION_DATABASE_URL || 'mysql://placeholder:placeholder@localhost:3306/placeholder' }} + + - name: Validate no schema drift + run: | + echo "Checking prisma schema is formatted..." + npx prisma format + if ! git diff --exit-code prisma/schema.prisma; then + echo "::error::prisma/schema.prisma has unformatted changes. Run 'npx prisma format' locally." + exit 1 + fi + + - name: Validate prisma generate output + run: | + if [ ! -f node_modules/.prisma/client/index.js ]; then + echo "::error::Prisma Client not generated" + exit 1 + fi + + # ═══════════════════════════════════════════════════════════════ + # 2. Dry-run migration (check what would be applied) + # ═══════════════════════════════════════════════════════════════ + + dry-run: + name: Dry-Run Migration + runs-on: ubuntu-latest + timeout-minutes: 10 + needs: validate + services: + mysql: + image: mysql:8.0 + env: + MYSQL_ROOT_PASSWORD: testpass + MYSQL_DATABASE: zhixi_test + ports: + - 3306:3306 + options: >- + --health-cmd "mysqladmin ping -h localhost" + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + cache: 'npm' + - run: npm ci + - run: npx prisma generate + env: + DATABASE_URL: mysql://root:testpass@127.0.0.1:3306/zhixi_test + + - name: Push schema to temp DB + run: npx prisma db push --skip-generate --accept-data-loss + env: + DATABASE_URL: mysql://root:testpass@127.0.0.1:3306/zhixi_test + + - name: Apply migrations + run: npx prisma migrate deploy + env: + DATABASE_URL: mysql://root:testpass@127.0.0.1:3306/zhixi_test + + - name: Verify migration completed + run: npx prisma migrate status + env: + DATABASE_URL: mysql://root:testpass@127.0.0.1:3306/zhixi_test + + # ═══════════════════════════════════════════════════════════════ + # 3. Deploy migration (staging/production) + # ═══════════════════════════════════════════════════════════════ + + deploy-migration: + name: Deploy Migration + runs-on: ubuntu-latest + timeout-minutes: 10 + needs: dry-run + if: github.event_name == 'workflow_dispatch' && inputs.run_deploy + environment: staging + steps: + - uses: actions/checkout@v4 + + - name: Deploy migration via SSH + uses: appleboy/ssh-action@v1 + with: + host: ${{ secrets.DEPLOY_HOST }} + username: ${{ secrets.DEPLOY_USER }} + key: ${{ secrets.DEPLOY_SSH_KEY }} + script: | + set -e + cd /opt/zhixi/api-server + + echo "=== Migration status before ===" + docker compose exec -T api npx prisma migrate status + + echo "=== Applying migrations ===" + docker compose exec -T api npx prisma migrate deploy + + echo "=== Migration status after ===" + docker compose exec -T api npx prisma migrate status