So, about migrations. Every time we change the way the database structure works, we need to add a migration so that people running older codebases can have their databases updated to the new structure when they run ./bin/gmg dbupdate.

The first time ./bin/gmg dbupdate is run by a user, it creates the tables at the current state that they’re defined in models.py and sets the migration number to the current migration... after all, migrations only exist to get things to the current state of the db. After that, every migration is run with dbupdate.

There’s a few things you need to know:

  • We use Alembic to run migrations. We also make heavy use of the branching model for our plugins. Every plugin gets its own migration branc.
  • We used to use sqlalchemy-migrate. See their docs. sqlalchemy-migrate is now only kept around for legacy migrations; don’t add any more! But some users are still using older databases, and we need to provide the intermediary “old” migrations for a while.
  • SQLAlchemy has two parts to it, the ORM and the “core” interface. We DO NOT use the ORM when running migrations. Think about it: the ORM is set up with an expectation that the models already reflect a certain pattern. But if a person is moving from their old patern and are running tools to get to the current pattern, of course their current database structure doesn’t match the state of the ORM! Anyway, Alembic has its own conventions for migrations; follow those.
  • Alembic’s documentation is pretty good; you don’t need to worry about setting up the migration environment or the config file so you can skip those parts. You can start at the Create a Migration Script section.
  • Users should only use ./bin/gmg dbupdate. However, developers may wish to use the ./bin/gmg alembic subcommand, which wraps alembic’s own command line interface. Alembic has some tools for autogenerating migrations, and they aren’t perfect, but they are helpful. (You can pass in ./bin/gmg alembic –with-plugins revision –autogenerate if you need to include plugins in the generated output; see the plugin database chapter for more info.)

That’s it for now! Good luck!