safe-migrate is an essential CI/CD tool designed to ensure PostgreSQL database migrations are safe. By analyzing migration scripts against real-time database statistics, it helps identify potentially catastrophic locks. This ensures smooth deployments and protects production environments from unexpected outages.
safe-migrate is a powerful Command-Line Interface (CLI) tool designed to safeguard PostgreSQL database migrations, effectively preventing production outages due to problematic locking issues. By leveraging static SQL analysis and real-time database statistics, it ensures that database alterations are handled safely.
Key Features
- Comprehensive Analysis: Unlike standard SQL linters that solely focus on the SQL syntax,
safe-migrateassesses both the SQL commands and the size of the affected tables. For example, adding a column to a 500-row table is safe, but the same operation on a 50 million-row table could trigger anACCESS EXCLUSIVElock, jeopardizing application availability.
How It Works
- Synchronization: The tool connects to the database to gather approximate row counts from
pg_classand writes this data to a.safe-migrate-stats.jsoncache file without storing any credentials. This step prepares the necessary information for the subsequent analysis.export DATABASE_URL="postgres://user:pass@localhost:5432/mydb"
safe-migrate sync
2. **Linting:** Using the cached data, `safe-migrate` analyzes migration files for potential locking problems. Each SQL statement is parsed into a typed Abstract Syntax Tree (AST), and the tool checks for dangerous locks against cached row counts.
```bash
safe-migrate lint --file migration.sql
Output and Risk Assessment
The tool provides detailed output regarding migration risks, classified into tiers based on the types of locks they generate:
| Tier | Lock Type | Default Behavior |
|---|---|---|
| Tier 1 | ACCESS EXCLUSIVE | Halts the build |
| Tier 2 | SHARE ROW EXCLUSIVE | Warns, continues |
| Tier 3 | Safe / non-blocking | Silent pass |
For instance, it might output a warning if adding a column to a table is risky, along with suggestions for safer procedures.
Configuration Options
Customize the behavior of safe-migrate by creating a safe-migrate.toml file in your repository's root directory, where thresholds can be adjusted per migration rule.
# Global row count threshold (default: 100,000)
default_threshold = 200000
[rules.adding-field-with-default]
tier = "Tier2"
threshold = 50000
CI/CD Integration
Integrate safe-migrate into Continuous Integration/Continuous Deployment (CI/CD) pipelines to continually safeguard migrations. An example YAML configuration is provided to show how to use it in a GitHub Actions workflow:
name: Safe Migrate
on:
pull_request:
branches: [ "main" ]
jobs:
lint-migrations:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install safe-migrate
run: curl -fsSL https://raw.githubusercontent.com/dsecurity49/safe-migrate/main/install.sh | bash
- name: Sync database stats
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }}
run: safe-migrate sync --out prod-cache.json
- name: Lint new migrations
run: |
FILES=$(git diff --name-only origin/${{ github.base_ref }}...HEAD -- '*.sql')
if [ -z "$FILES" ]; then
echo "No SQL migrations changed. Skipping."
exit 0
fi
for f in $FILES; do
echo "Linting $f..."
safe-migrate lint --file "$f" --cache prod-cache.json
done
With safe-migrate, database migrations become more manageable and less prone to producing downtime, ensuring the stability of production environments.
No comments yet.
Sign in to be the first to comment.