diff --git a/.github/workflows/chatops-migrate.yml b/.github/workflows/chatops-migrate.yml new file mode 100644 index 0000000..958f8a6 --- /dev/null +++ b/.github/workflows/chatops-migrate.yml @@ -0,0 +1,171 @@ +name: ChatOps Migration Deployment + +on: + issue_comment: + types: [created] + +env: + BYTEBASE_URL: https://demo.bytebase.com + BYTEBASE_SERVICE_ACCOUNT: api@service.bytebase.com + BYTEBASE_SERVICE_ACCOUNT_SECRET: ${{ secrets.BYTEBASE_SERVICE_ACCOUNT_SECRET }} + BYTEBASE_PROJECT: "projects/hr" + +jobs: + parse-command: + if: github.event.issue.pull_request && startsWith(github.event.comment.body, '/migrate') + runs-on: ubuntu-latest + outputs: + environment: ${{ steps.parse.outputs.environment }} + valid-command: ${{ steps.parse.outputs.valid-command }} + steps: + - name: Parse migrate command + id: parse + run: | + COMMENT="${{ github.event.comment.body }}" + echo "Comment: $COMMENT" + + # Extract environment from "/migrate " + if [[ $COMMENT =~ ^/migrate[[:space:]]+([a-zA-Z]+) ]]; then + ENVIRONMENT="${BASH_REMATCH[1]}" + echo "Parsed environment: $ENVIRONMENT" + + # Validate environment + case $ENVIRONMENT in + test|prod) + echo "environment=$ENVIRONMENT" >> $GITHUB_OUTPUT + echo "valid-command=true" >> $GITHUB_OUTPUT + echo "✅ Valid environment: $ENVIRONMENT" + ;; + *) + echo "valid-command=false" >> $GITHUB_OUTPUT + echo "❌ Invalid environment: $ENVIRONMENT" + ;; + esac + else + echo "valid-command=false" >> $GITHUB_OUTPUT + echo "❌ Invalid command format" + fi + + - name: Add reaction to comment + if: steps.parse.outputs.valid-command == 'true' + uses: peter-evans/create-or-update-comment@v3 + with: + comment-id: ${{ github.event.comment.id }} + reactions: rocket + + - name: Comment on invalid command + if: steps.parse.outputs.valid-command == 'false' + uses: peter-evans/create-or-update-comment@v3 + with: + issue-number: ${{ github.event.issue.number }} + body: | + ❌ Invalid migrate command. + + **Usage:** `/migrate ` + **Valid environments:** `test`, `prod` + + **Example:** `/migrate test` + reactions: confused + + deploy: + needs: parse-command + if: needs.parse-command.outputs.valid-command == 'true' + runs-on: ubuntu-latest + environment: ${{ needs.parse-command.outputs.environment }} + container: + image: bytebase/bytebase-action:latest + steps: + - name: Checkout PR merge commit + uses: actions/checkout@v4 + with: + ref: refs/pull/${{ github.event.issue.number }}/merge + + - name: Comment deployment started + uses: peter-evans/create-or-update-comment@v3 + with: + issue-number: ${{ github.event.issue.number }} + body: | + 🚀 **Migration deployment started** + + **Environment:** `${{ needs.parse-command.outputs.environment }}` + **PR:** #${{ github.event.issue.number }} + **Triggered by:** @${{ github.event.comment.user.login }} + + Deploying database changes... + + - name: Set environment-specific targets + id: env-config + run: | + case "${{ needs.parse-command.outputs.environment }}" in + test) + echo "bytebase-targets=instances/test-sample-instance/databases/hr_test" >> $GITHUB_OUTPUT + echo "bytebase-stage=environments/test" >> $GITHUB_OUTPUT + ;; + prod) + echo "bytebase-targets=instances/prod-sample-instance/databases/hr_prod" >> $GITHUB_OUTPUT + echo "bytebase-stage=environments/prod" >> $GITHUB_OUTPUT + ;; + esac + + - name: Create rollout plan + id: create-rollout + env: + BYTEBASE_TARGETS: ${{ steps.env-config.outputs.bytebase-targets }} + FILE_PATTERN: "migrations-semver/*.sql" + BYTEBASE_OUTPUT: ${{ runner.temp }}/bytebase-metadata.json + run: | + echo "Creating rollout plan for ${{ needs.parse-command.outputs.environment }}..." + + bytebase-action rollout \ + --url=${{ env.BYTEBASE_URL }} \ + --service-account=${{ env.BYTEBASE_SERVICE_ACCOUNT }} \ + --service-account-secret=${{ env.BYTEBASE_SERVICE_ACCOUNT_SECRET }} \ + --project=${{ env.BYTEBASE_PROJECT }} \ + --file-pattern=${{ env.FILE_PATTERN }} \ + --targets=${{ env.BYTEBASE_TARGETS }} \ + --output=${{ env.BYTEBASE_OUTPUT }} + + PLAN=$(jq -r .plan ${{ runner.temp }}/bytebase-metadata.json) + echo "plan=$PLAN" >> $GITHUB_OUTPUT + + - name: Execute rollout + env: + BYTEBASE_TARGET_STAGE: ${{ steps.env-config.outputs.bytebase-stage }} + run: | + echo "Executing rollout to ${{ needs.parse-command.outputs.environment }}..." + + bytebase-action rollout \ + --url=${{ env.BYTEBASE_URL }} \ + --service-account=${{ env.BYTEBASE_SERVICE_ACCOUNT }} \ + --service-account-secret=${{ env.BYTEBASE_SERVICE_ACCOUNT_SECRET }} \ + --project=${{ env.BYTEBASE_PROJECT }} \ + --target-stage=${{ env.BYTEBASE_TARGET_STAGE }} \ + --plan=${{ steps.create-rollout.outputs.plan }} + + - name: Comment deployment success + if: success() + uses: peter-evans/create-or-update-comment@v3 + with: + issue-number: ${{ github.event.issue.number }} + body: | + ✅ **Migration deployment completed successfully** + + **Environment:** `${{ needs.parse-command.outputs.environment }}` + **PR:** #${{ github.event.issue.number }} + **Triggered by:** @${{ github.event.comment.user.login }} + + Database schema has been updated in the `${{ needs.parse-command.outputs.environment }}` environment. + + - name: Comment deployment failure + if: failure() + uses: peter-evans/create-or-update-comment@v3 + with: + issue-number: ${{ github.event.issue.number }} + body: | + ❌ **Migration deployment failed** + + **Environment:** `${{ needs.parse-command.outputs.environment }}` + **PR:** #${{ github.event.issue.number }} + **Triggered by:** @${{ github.event.comment.user.login }} + + Please check the [workflow run](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) for details. diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..41ff274 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,67 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +This is a GitOps demonstration repository for database CI/CD using Bytebase and GitHub Actions with GitHub Flow. The repository shows how to integrate database schema changes with application deployment pipelines. + +## Repository Structure + +- `migrations-semver/`: Contains SQL migration files following semantic versioning naming convention (e.g., `1.0.0_init.sql`, `1.1.1_comment.sql`) +- `schema/`: Contains base database schema definitions +- `.github/workflows/`: GitHub Actions workflows for CI/CD pipeline + +## Migration File Naming + +Migration files MUST follow semantic versioning pattern: `{major}.{minor}.{patch}_{description}.sql` +- Examples: `1.0.0_init.sql`, `1.1.1_comment.sql`, `1.13.0_phone.sql` +- Files are processed by Bytebase in semantic version order + +## GitHub Actions Workflows + +### SQL Review Workflow (`sql-review-action.yml`) +- Triggers on pull requests to `main` branch when `migrations-semver/*.sql` files change +- Uses `bytebase/bytebase-action:latest` Docker image +- Runs SQL validation against production database +- Requires `BYTEBASE_SERVICE_ACCOUNT_SECRET` repository secret + +### Release Workflow (`release-action.yml`) +- Triggers on push to `main` branch when `migrations-semver/*.sql` files change +- Three-stage process: + 1. `build`: Mock application build step + 2. `create-rollout`: Creates Bytebase rollout plan for both test and prod databases + 3. `deploy-to-test`: Deploys to test environment automatically + 4. `deploy-to-prod`: Deploys to production (requires manual approval via GitHub environment protection) + +## Environment Configuration + +Both workflows use these environment variables: +- `BYTEBASE_URL`: Bytebase instance URL +- `BYTEBASE_SERVICE_ACCOUNT`: Service account email +- `BYTEBASE_SERVICE_ACCOUNT_SECRET`: Service account password (stored in GitHub secrets) +- `BYTEBASE_PROJECT`: Target Bytebase project +- `BYTEBASE_TARGETS`: Comma-separated list of database targets +- `FILE_PATTERN`: Glob pattern for migration files (`migrations-semver/*.sql`) + +## Database Schema + +The schema includes: +- Employee management system with tables: `employee`, `department`, `dept_manager`, `dept_emp`, `title`, `salary` +- Audit logging system with trigger-based change tracking +- Views for current department assignments + +## Development Workflow + +1. Create feature branch +2. Add SQL migration files to `migrations-semver/` with proper semantic versioning +3. Create pull request - triggers SQL review workflow +4. Merge to main - triggers release workflow +5. Test environment deployment happens automatically +6. Production deployment requires manual approval through GitHub environment protection + +## Key Integration Points + +- All database changes go through Bytebase for review and deployment +- GitHub environment protection rules control production deployments +- Migration files are validated against actual database schemas during PR review \ No newline at end of file