databasesqlalchemymigrationalembic

Dynamically set up the version_locations in env.py for alembic migrations


I am using alembic to manage my database changes. Other people may also add changes to this database. Everything is set up correctly and this is currebtly working fine.
However, because we are many to modify the db and therefore create new .py for each modifications, I wanted to move the "version" folder away from my github repo to avoid flooding it.
The version folder would then be accessible to a distant server.
We can acess the server from our local machines via sshfs therefore guy1 may have the server to /mnt/myserver, and guy2 to /home/myserver.

I would like then to be able to change the version_locations to path_to_server/versions. I didnt manage to do so using the env.py to do it dynamically. Any idea on how to do so ?

So far the plan was:

my_server_path = os.environ.get("my_server_path")
context.script.version_locations = f"{my_server_path}/versions"

I've also tried with config.set_main_option("version_locations",f"{my_server_path}/versions") and to change the revision_environment in the alembic.ini to true or false, but didnt work either.

At best I had alembic telling me FAILED: Multiple version locations present, please specify --version-path, but it doesnt make sense to specify a path when there should only be one in the beginning.


Solution

  • One of the maintainers mentions here the below hack to enable specifying this programmatically.

    env.py

    from alembic import context
    import os
    
    script = context.script
    
    def get_versions_path():
      try:
        versions_path = os.environ['ALEMBIC_VERSIONS_PATH']
      except KeyError:
        raise ValueError('You must specify a value for ALEMBIC_VERSIONS_PATH, which is the path to the /versions directory')
    
      if not os.path.isdir(versions_path):
        raise ValueError(f"ALEMBIC_VERSIONS_PATH of '{versions_path}' does not exist")
    
      return versions_path
    
    script.__dict__.pop('_version_locations', None)
    script.version_locations = [get_versions_path()]
    

    Feel free to modify get_versions_path to your liking.