dak.c2s/backend/alembic/env.py
CCS Admin 4649f7a082 feat: Alembic migrations, initial schema
- Initialize Alembic with MySQL/MariaDB-targeted configuration
- Configure env.py to read DB URL from app.config.get_settings()
- Create initial migration (062ccae5457b) for all 11 tables:
  users, refresh_tokens, invitation_links, allowed_domains,
  cases, case_icd_codes, weekly_reports, yearly_summary,
  import_log, audit_log, notifications
- Include all indexes, foreign keys, check constraints, and
  MySQL text prefix index (icd(20))
- Add seed script (scripts/init_db.py) for dak.de domain whitelist
- DB apply deferred: MariaDB on Hetzner 1 not reachable from dev

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 07:33:27 +00:00

86 lines
2.6 KiB
Python

"""Alembic environment configuration for DAK Zweitmeinungs-Portal."""
import sys
import os
from logging.config import fileConfig
from sqlalchemy import engine_from_config, pool
from alembic import context
# ---------------------------------------------------------------------------
# Ensure the backend package is importable.
# alembic is invoked from backend/, so '.' is already on sys.path via
# alembic.ini's `prepend_sys_path = .`, but we add it explicitly to be safe.
# ---------------------------------------------------------------------------
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from app.database import Base # noqa: E402
from app.models import * # noqa: E402, F401, F403 — register all models with metadata
from app.config import get_settings # noqa: E402
# ---------------------------------------------------------------------------
# Alembic Config object — provides access to the .ini file values.
# ---------------------------------------------------------------------------
config = context.config
# Interpret the config file for Python logging.
if config.config_file_name is not None:
fileConfig(config.config_file_name)
# The MetaData object for 'autogenerate' support.
target_metadata = Base.metadata
def get_url() -> str:
"""Return the database URL from application settings."""
return get_settings().database_url
def run_migrations_offline() -> None:
"""Run migrations in 'offline' mode.
This configures the context with just a URL and not an Engine,
so we don't need a DBAPI to be available.
Calls to context.execute() emit the given string to the script output.
"""
url = get_url()
context.configure(
url=url,
target_metadata=target_metadata,
literal_binds=True,
dialect_opts={"paramstyle": "named"},
)
with context.begin_transaction():
context.run_migrations()
def run_migrations_online() -> None:
"""Run migrations in 'online' mode.
Creates an Engine and associates a connection with the context.
"""
configuration = config.get_section(config.config_ini_section, {})
configuration["sqlalchemy.url"] = get_url()
connectable = engine_from_config(
configuration,
prefix="sqlalchemy.",
poolclass=pool.NullPool,
)
with connectable.connect() as connection:
context.configure(
connection=connection,
target_metadata=target_metadata,
)
with context.begin_transaction():
context.run_migrations()
if context.is_offline_mode():
run_migrations_offline()
else:
run_migrations_online()