Skip to main content

Safely converge Alembic migration graphs by generating minimal merge migrations

Project description

Alembic Converger

PyPI version Documentation Status Python Support License: MIT

Safely converge Alembic migration graphs by automatically generating minimal merge migrations.

Alembic Converger is a production-grade Python tool that detects and resolves multiple migration heads in your Alembic migration history. It creates graph-only merge migrations without modifying schema operations, ensuring safe convergence for teams working with parallel database migrations.

The Problem

When multiple developers work on database migrations in parallel, or when merging feature branches, you often end up with multiple heads in your Alembic migration graph:

        [feature-1]  [feature-2]
              |           |
           rev-abc     rev-def
                \       /
                 \     /
                [main branch]
                    |
                  rev-123

Alembic requires a single linear path to head, and having multiple heads can cause:

  • Failed deployments
  • CI/CD pipeline failures
  • Confusion about which migrations to apply

Why Alembic Converger?

Traditional approach:

# Manual merge - error-prone and time-consuming
alembic merge -m "merge heads" rev-abc rev-def
# Did it create schema conflicts? Who knows! 😰

With Alembic Converger:

# Automatic, safe convergence
alembic-converger converge --from-revision rev-123
# ✓ Validates merge is graph-only
# ✓ Tests upgrade path automatically
# ✓ Fails fast on conflicts

Safety Guarantees

🔒 This tool is designed to be safe by default:

  1. Never modifies existing migrations - Only creates new merge migrations
  2. Never guesses developer intent - Only performs graph-only merges
  3. Never auto-resolves schema conflicts - Fails if merge contains operations
  4. Validates upgrade path - Runs alembic upgrade after each merge
  5. Deterministic behavior - Same input always produces same result
  6. Automatic rollback - Deletes created merges on failure

Installation

pip install alembic-converger

Requirements:

  • Python 3.8+
  • Alembic 1.7.0+

Quick Start

Basic Usage

# Converge all heads from a base revision
alembic-converger converge --from-revision ae1027a6acf

# Dry run to preview changes
alembic-converger converge --from-revision ae1027a6acf --dry-run

# Skip database validation (faster, less safe)
alembic-converger converge --from-revision ae1027a6acf --skip-validation

# Verbose output for debugging
alembic-converger converge --from-revision ae1027a6acf --verbose

Python API

from alembic_converger import converge_migrations

# Programmatic convergence
result = converge_migrations(
    base_revision="ae1027a6acf",
    config_path="alembic.ini",
    dry_run=False,
    skip_validation=False,
    verbose=True
)

print(f"Created {len(result.merges_created)} merge(s)")
print(f"Final head: {result.final_head}")

How It Works

Alembic Converger treats your migrations as a directed acyclic graph (DAG):

  1. Discovery: Find all heads descending from a known base revision
  2. Validation: Ensure all heads share a common ancestor
  3. Convergence: Iteratively merge heads pairwise until one remains
  4. Verification: After each merge:
    • Validate the merge contains no schema operations
    • Run alembic upgrade to test the path
    • Reload the graph and continue

Example Scenario

Initial state (3 heads):
    head-1    head-2    head-3
       \        |        /
        \       |       /
         base (ae1027a6acf)

After convergence:
         final-head
            |
        merge-2
          /   \
     merge-1  head-3
       /  \
   head-1 head-2
       \   |   /
         base

CI/CD Integration

GitHub Actions

name: Check Alembic Convergence

on: [pull_request]

jobs:
  check-migrations:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Set up Python
        uses: actions/setup-python@v4
        with:
          python-version: '3.11'
      
      - name: Install dependencies
        run: |
          pip install alembic-converger
          pip install -r requirements.txt
      
      - name: Check for multiple heads
        run: |
          # Get the base revision (e.g., from main branch)
          BASE_REV=$(git merge-base origin/main HEAD)
          
          # Try to converge (will fail if conflicts exist)
          alembic-converger converge \
            --from-revision $BASE_REV \
            --dry-run

Pre-deployment Hook

#!/bin/bash
# deploy.sh

echo "Checking for multiple Alembic heads..."
alembic-converger converge --from-revision $(git describe --tags --abbrev=0) --dry-run

if [ $? -eq 0 ]; then
  echo "✓ Migrations converged"
  # Continue with deployment
else
  echo "✗ Migration convergence failed"
  exit 1
fi

CLI Reference

converge Command

alembic-converger converge [OPTIONS]

Options:
  --from-revision TEXT     Base revision to converge from [required]
  --alembic-config TEXT    Path to alembic.ini [default: alembic.ini]
  --dry-run               Show what would be done without changes
  --skip-validation       Skip upgrade validation (not recommended)
  --verbose, -v           Enable debug logging
  --help                  Show this message and exit

Exit Codes

  • 0: Success (already converged or successfully merged)
  • 1: Convergence failed (validation error, conflicts, etc.)
  • 2: Configuration error (invalid alembic.ini, missing files, etc.)

FAQ

Why not just use alembic merge?

alembic merge creates a single merge migration but:

  • Doesn't validate the merge is conflict-free
  • Doesn't test the upgrade path
  • Requires manual intervention for each merge
  • Can silently create broken migrations

Alembic Converger automates this safely with validation.

Why not auto-resolve schema conflicts?

Safety first. Schema conflicts require developer judgment:

  • Which column definition to keep?
  • How to handle conflicting constraints?
  • What about data migrations?

Auto-resolving could cause data loss or corruption. Instead, we fail fast and let you resolve manually.

When should I use this tool?

Perfect for:

  • ✅ CI/CD pipelines (pre-deployment checks)
  • ✅ Multi-developer teams with parallel migrations
  • ✅ Feature branch merges
  • ✅ Automated migration management

Not suitable for:

  • ❌ Resolving schema conflicts (requires manual intervention)
  • ❌ Rewriting migration history (never modifies existing files)

What if validation fails?

When validation fails, Alembic Converger:

  1. Logs the detailed error
  2. Rolls back created merge migrations
  3. Exits with code 1

You'll need to manually resolve conflicts:

# Review the conflicting migrations
alembic history --verbose

# Manually create merge with conflict resolution
alembic merge -m "resolve conflicts" rev-1 rev-2
# Edit the generated file to resolve conflicts

Can I use this without a database?

Yes, with --skip-validation:

alembic-converger converge --from-revision X --skip-validation

However, this skips upgrade testing, reducing safety guarantees. Use only when:

  • Database is not available (e.g., CI without DB)
  • You'll test manually later

Architecture

Alembic Converger is built with clean separation of concerns:

alembic_converger/
├── cli.py          # Click-based CLI interface
├── config.py       # Alembic configuration loading
├── graph.py        # DAG analysis & traversal
├── merge.py        # Merge creation & validation
├── validate.py     # Upgrade path testing
├── converge.py     # Main orchestration algorithm
├── errors.py       # Exception hierarchy
└── utils.py        # Shared utilities

Key Design Principles

  1. Graph-first thinking: Migrations are nodes in a DAG, not files
  2. Fail fast: Detect problems early with clear errors
  3. Idempotent: Same input → same output every time
  4. No side effects: Only creates merge files, never modifies existing ones
  5. Observable: Comprehensive logging at every step

Development

Setup

# Clone the repository
git clone https://github.com/rishav00a/alembic_converger.git
cd alembic_converger

# Create virtual environment
python -m venv venv
source venv/bin/activate  # or `venv\Scripts\activate` on Windows

# Install in development mode
pip install -e ".[dev]"

Running Tests

# Run all tests
pytest

# With coverage
pytest --cov=alembic_converger --cov-report=html

# Run specific test file
pytest tests/test_graph.py -v

Code Quality

# Format code
black alembic_converger tests

# Lint code
ruff check alembic_converger tests

# Type checking (optional)
mypy alembic_converger

Publishing to PyPI

# Install build tools
pip install build twine

# Build distribution
python -m build

# Check package
twine check dist/*

# Upload to TestPyPI (optional)
twine upload --repository testpypi dist/*

# Upload to PyPI
twine upload dist/*

Contributing

Contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Make your changes with tests
  4. Run tests and linting
  5. Commit your changes (git commit -m 'Add amazing feature')
  6. Push to the branch (git push origin feature/amazing-feature)
  7. Open a Pull Request

License

This project is licensed under the MIT License - see the LICENSE file for details.

Credits

Built with ❤️ by the open-source community.

Powered by:

  • Alembic - Database migrations for SQLAlchemy
  • Click - Command-line interface creation
  • Colorama - Cross-platform colored terminal text

Support


Remember: This tool is a graph normalizer, not a migration author. It safely converges parallel development paths without guessing your intent. ✨

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

alembic_converger-0.1.4.tar.gz (21.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

alembic_converger-0.1.4-py3-none-any.whl (19.5 kB view details)

Uploaded Python 3

File details

Details for the file alembic_converger-0.1.4.tar.gz.

File metadata

  • Download URL: alembic_converger-0.1.4.tar.gz
  • Upload date:
  • Size: 21.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.0

File hashes

Hashes for alembic_converger-0.1.4.tar.gz
Algorithm Hash digest
SHA256 8f0f52c94b47e7392b7b31299c86cc3668edf349ac8cd36e3248a6eba377f9bc
MD5 3393895979300793c39337d37307bc15
BLAKE2b-256 0f5e6835c7d95cf09b955a23efe273cf41e867a9cde86a2ed5e7b24902c4670c

See more details on using hashes here.

File details

Details for the file alembic_converger-0.1.4-py3-none-any.whl.

File metadata

File hashes

Hashes for alembic_converger-0.1.4-py3-none-any.whl
Algorithm Hash digest
SHA256 0ce05c360f8f69ddfcf237e338b4f3ab200d2b4b53d3897f9df214a46755ed23
MD5 2632eada2b01985364252b020e8a05cc
BLAKE2b-256 1897da2f6fd263afa2238526a55e411f58448665fa2a53e7c2b1ae44ae772a42

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page