GitHub Actions Integration

Automatically check for migration issues in your CI/CD pipeline using Rails Migration Guard with GitHub Actions.

Quick Start

Add this workflow to your repository to check for migration issues on every pull request:

# .github/workflows/migration-check.yml
name: Migration Check

on:
  pull_request:
    branches: [ main, master ]

jobs:
  check-migrations:
    runs-on: ubuntu-latest
    
    services:
      postgres:
        image: postgres:14
        env:
          POSTGRES_PASSWORD: postgres
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
        ports:
          - 5432:5432
    
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0  # Required for branch comparison
      
      - name: Set up Ruby
        uses: ruby/setup-ruby@v1
        with:
          bundler-cache: true
      
      - name: Setup database
        env:
          DATABASE_URL: postgresql://postgres:postgres@localhost:5432/test
          RAILS_ENV: test
        run: |
          bundle exec rails db:create
          bundle exec rails db:schema:load
      
      - name: Check for migration issues
        env:
          DATABASE_URL: postgresql://postgres:postgres@localhost:5432/test
          RAILS_ENV: test
        run: |
          bundle exec rails db:migration:ci --strict

Pro Tip: Rails Migration Guard also includes a GitHub Action that provides additional features like automatic PR comments. Use uses: ./.github/actions/migration-guard instead of the CLI command.

Configuration Options

Command Line Options

Option Description Default
--strict Fail on warnings false
--format Output format (text/json) text

Exit Codes

  • 0 No issues found
  • 1 Warnings found (orphaned migrations)
  • 2 Errors found (missing migrations)

Database Services

PostgreSQL

services:
  postgres:
    image: postgres:14
    env:
      POSTGRES_PASSWORD: postgres
    ports:
      - 5432:5432

MySQL

services:
  mysql:
    image: mysql:8
    env:
      MYSQL_ROOT_PASSWORD: pass
      MYSQL_DATABASE: test_db
    ports:
      - 3306:3306

SQLite

# No service needed
env:
  DATABASE_URL: sqlite3:db/test.sqlite3
  RAILS_ENV: test

Advanced Examples

Matrix Testing

Test across multiple Ruby and Rails versions

strategy:
  matrix:
    ruby: ['3.1', '3.2', '3.3']
    rails: ['7.0', '7.1', '7.2']
    
steps:
  - uses: ruby/setup-ruby@v1
    with:
      ruby-version: $
      bundler-cache: true
  
  - name: Check migrations
    run: bundle exec rails db:migration:ci

Conditional Checks

Only run when migrations change

on:
  pull_request:
    paths:
      - 'db/migrate/**'
      - 'db/schema.rb'
      - 'db/structure.sql'

Scheduled Monitoring

Check for drift in staging environments

on:
  schedule:
    - cron: '0 9 * * 1-5'  # 9 AM UTC on weekdays
    
jobs:
  check-drift:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          ref: main
      
      - name: Check staging migrations
        env:
          RAILS_ENV: staging
          DATABASE_URL: $
        run: bundle exec rails db:migration:ci

JSON Output Parsing

Use JSON format for advanced workflows and automated processing:

Workflow Example

- name: Check migrations
  id: migration_check
  env:
    DATABASE_URL: $
  run: |
    bundle exec rails db:migration:ci \
      --format json > result.json || true
    echo "orphaned_count=$(jq '.orphaned | length' result.json)" \
      >> $GITHUB_OUTPUT
    
- name: Comment on PR
  if: steps.migration_check.outputs.orphaned_count > 0
  uses: actions/github-script@v6
  with:
    script: |
      github.rest.issues.createComment({
        issue_number: context.issue.number,
        owner: context.repo.owner,
        repo: context.repo.repo,
        body: '⚠️ Found orphaned migrations'
      })

JSON Output Format

{
  "status": "warning",
  "orphaned": [
    {
      "version": "20240115123456",
      "name": "add_user_profiles",
      "branch": "feature/profiles",
      "author": "developer@example.com"
    }
  ],
  "missing": [],
  "synced": [
    "20240110111111",
    "20240112222222"
  ]
}

Best Practices

1

Use fetch-depth: 0

The gem needs full git history to compare branches

2

Start with warnings

Use --strict only after your team is comfortable

3

Cache dependencies

Always use bundler-cache: true for speed

4

Secure credentials

Always use secrets for database URLs

5

Run in parallel

Migration checks can run alongside tests

6

Monitor drift

Set up scheduled checks for staging

Troubleshooting

"fetch-depth: 0 is required"

The gem needs full git history to compare branches:

- uses: actions/checkout@v4
  with:
    fetch-depth: 0  # Don't use shallow clone

Database connection errors

Ensure your database service is healthy:

- name: Wait for PostgreSQL
  run: |
    until pg_isready -h localhost -p 5432; do
      echo "Waiting for PostgreSQL..."
      sleep 1
    done

Permission denied for PR comments

When using the built-in action with PR comments:

permissions:
  contents: read
  pull-requests: write