/ migrate.py
migrate.py
 1  """Alembic migration runner.
 2  
 3  Stdlib-only on purpose: this file runs as the very first step of
 4  `make update`, before `uv sync` has had a chance to install anything
 5  new from `pyproject.toml`. Adding a third-party CLI dep here means an
 6  old instance whose .venv is missing that dep can't even reach the
 7  migrations to fix the upgrade. argparse keeps this script bootable
 8  under any Python 3 install.
 9  """
10  import argparse
11  
12  from alembic.config import Config
13  from alembic import command
14  
15  from restai.config import POSTGRES_URL, MYSQL_URL, POSTGRES_HOST, MYSQL_HOST
16  
17  
18  def get_database_url():
19      if POSTGRES_HOST:
20          return POSTGRES_URL
21      elif MYSQL_HOST:
22          return MYSQL_URL
23      else:
24          return "sqlite:///./restai.db"
25  
26  
27  def _alembic_cfg():
28      cfg = Config("alembic.ini")
29      cfg.set_main_option("sqlalchemy.url", get_database_url())
30      return cfg
31  
32  
33  def upgrade():
34      """Run database migrations to upgrade the database schema."""
35      command.upgrade(_alembic_cfg(), "head")
36  
37  
38  def downgrade():
39      """Run database migrations to downgrade the database schema."""
40      command.downgrade(_alembic_cfg(), "-1")
41  
42  
43  def main():
44      parser = argparse.ArgumentParser(
45          description="Run Alembic migrations against the configured database.",
46      )
47      sub = parser.add_subparsers(dest="cmd", required=True)
48      sub.add_parser("upgrade", help="Upgrade to the latest revision (alembic head).")
49      sub.add_parser("downgrade", help="Downgrade by one revision (alembic -1).")
50      args = parser.parse_args()
51  
52      if args.cmd == "upgrade":
53          upgrade()
54      elif args.cmd == "downgrade":
55          downgrade()
56  
57  
58  if __name__ == "__main__":
59      main()