Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I check if Alembic migrations need to be generated?

I'm trying to improve CI pipeline to prevent situations where SQLAlchemy models are added or changed, but no Alembic migration is written or generated by the commit author from hitting the production branch.

alembic --help doesn't seem to provide any helpful commands for this case, yet it already has all the metadata required (target_metadata variable) and the database credentials in env.py to make this happen.

What would be the best practice for implementing this check in CI?

like image 209
Nikolay Edigaryev Avatar asked Apr 22 '20 20:04

Nikolay Edigaryev


People also ask

How do you make migrations with alembic?

Alembic can view the status of the database and compare against the table metadata in the application, generating the “obvious” migrations based on a comparison. This is achieved using the --autogenerate option to the alembic revision command, which places so-called candidate migrations into our new migrations file.

How do I remove alembic migration?

There's currently no command to delete migrations from your versions directory, so if you want to completely wipe away all trace of your bad migration, you'll need to delete the version file (like 4c009570237e_add_widget_table.py ) manually.

How do I reset my alembic?

Right click on alembic. ini and choose git>rollback>ok.


2 Answers

Here's a solution that I use. It's a check that I have implemented as a test.

from alembic.autogenerate import compare_metadata
from alembic.command import upgrade
from alembic.runtime.migration import MigrationContext
from alembic.config import Config

from models.base import Base


def test_migrations_sane():
    """
    This test ensures that models defined by SQLAlchemy match what alembic migrations think
    the database should look like. If these are different, then once we have constructed
    the database via Alembic (via running all migrations) alembic will generate a set of changes to
    modify the database to match the schema defined by SQLAlchemy models. If these are the same,
    the set of changes is going to be empty. Which is exactly what we want to check.
    """
    engine = "SQLAlchemy DB Engine instance"
    try:
        with engine.connect() as connection:
            alembic_conf_file = "location of alembic.ini"
            alembic_config = Config(alembic_conf_file)
            upgrade(alembic_config, "head")
            mc = MigrationContext.configure(connection)
            diff = compare_metadata(mc, Base.metadata)

            assert diff == []
    finally:
        with engine.connect() as connection:
            # Resetting the DB
            connection.execute(
                """
                DROP SCHEMA public CASCADE;
                CREATE SCHEMA public;
                GRANT ALL ON SCHEMA public TO postgres;
                GRANT ALL ON SCHEMA public TO public;
                """
            )

EDIT: I noticed you linked a library that's supposed to do the same thing. I gave it a go but it seems like it assumes that the database that it's running the check against has to have had alembic run against it. My solution works against a blank db.

like image 81
Vladimirs Avatar answered Sep 21 '22 07:09

Vladimirs


There is alembic-autogen-check tool available: https://pypi.org/project/alembic-autogen-check/ Although it requires a database to be created to check upon.

like image 29
ziima Avatar answered Sep 19 '22 07:09

ziima