Set up alembic migration usage (#954)

* Set up alembic migration usage

* Fix import order, add isort as alembic hook

* Only run migrations if needed

* Include date as part of migration file name for better sorting

* Skip initial migrations if tables already exist
This eases the transition from a pre-alembic state

* Fix deprecation warning in alembic revision

* Add alembic test stubs
This commit is contained in:
Philipp Fischbeck
2022-02-21 21:44:23 +01:00
committed by GitHub
parent a897e180ed
commit fdfb5b1a5e
14 changed files with 1197 additions and 25 deletions

View File

@@ -1,7 +1,13 @@
from pathlib import Path
from sqlalchemy import engine
from alembic import command, config, script
from alembic.config import Config
from alembic.runtime import migration
from mealie.core import root_logger
from mealie.core.config import get_app_settings
from mealie.db.db_setup import create_session, engine
from mealie.db.models._model_base import SqlAlchemyBase
from mealie.db.db_setup import create_session
from mealie.repos.all_repositories import get_repositories
from mealie.repos.repository_factory import AllRepositories
from mealie.repos.seed.init_users import default_user_init
@@ -9,15 +15,11 @@ from mealie.repos.seed.seeders import IngredientFoodsSeeder, IngredientUnitsSeed
from mealie.schema.user.user import GroupBase
from mealie.services.group_services.group_utils import create_new_group
PROJECT_DIR = Path(__file__).parent.parent.parent
logger = root_logger.get_logger("init_db")
def create_all_models():
import mealie.db.models._all_models # noqa: F401
SqlAlchemyBase.metadata.create_all(engine)
def init_db(db: AllRepositories) -> None:
# TODO: Port other seed data to use abstract seeder class
default_group_init(db)
@@ -42,24 +44,33 @@ def default_group_init(db: AllRepositories):
create_new_group(db, GroupBase(name=settings.DEFAULT_GROUP))
# Adapted from https://alembic.sqlalchemy.org/en/latest/cookbook.html#test-current-database-revision-is-at-head-s
def db_is_at_head(alembic_cfg: config.Config) -> bool:
settings = get_app_settings()
url = settings.DB_URL
connectable = engine.create_engine(url)
directory = script.ScriptDirectory.from_config(alembic_cfg)
with connectable.begin() as connection:
context = migration.MigrationContext.configure(connection)
return set(context.get_current_heads()) == set(directory.get_heads())
def main():
create_all_models()
alembic_cfg = Config(str(PROJECT_DIR / "alembic.ini"))
if db_is_at_head(alembic_cfg):
logger.info("Migration not needed.")
else:
logger.info("Migration needed. Performing migration...")
command.upgrade(alembic_cfg, "head")
session = create_session()
db = get_repositories(session)
try:
init_user = db.users.get_all()
if not init_user:
raise Exception("No users found in database")
except Exception:
init_db(db)
return
init_user = db.users.get_all()
if init_user:
logger.info("Database Exists")
logger.info("Database exists")
else:
logger.info("Database Doesn't Exists, Initializing...")
logger.info("Database contains no users, initializing...")
init_db(db)