Search code examples
migrationelixirphoenix-frameworkectoumbrella

How to run migrations of another app from main app


I am following umbrella apps structure in my project. and I am writing access layer app which doesn't have separate repo but requires to have certain tables and relations migrated for it to work. I dont wanna create separate repo for it and make it complex to maintain configs etc.

I have tried following two approaches

defmodule Data.Repo.Migrations.CreateActions do
  use Ecto.Migration

  def change do
    # First approach
    opts = []
    file_path = ExAcl.SeedHelper.priv_path_for("20181129092126_create_actions.exs", app: :acl)
    Ecto.Migrator.run(Data.Repo, file_path, :up, opts)

    {:ok, _} = Application.ensure_all_started(:acl)

    # Second approach
    Ecto.Migrator.up(HaiData.Repo, 20181129092126, ExAcl.Repo.Migrations.CreateActions)
  end
end

But It doesn't run migrations in another app.

Maybe I am not going in right direction. I am not sure what is the best way to run migration in another app

Goal: run migrations in acl app via main data app.


Solution

  • If you try to run a migration via Ecto.Migrator.run from inside another migration, then you will most likely run into database locks, because Ecto doesn't allow you to run migrations concurrently.

    If you want to use this approach, then you can do this:

    def change do
      file_path = ExAcl.SeedHelper.priv_path_for("20181129092126_create_actions.exs", app: :acl)
      Code.require_file(file_path)
      ModuleInTheMigrationFile.change()
    end
    

    But I am not sure how maintainable this would be in the long term. If there are other migrations, then you would have to explicitly require and invoke each migration one by one. And then what happens for new migrations in the future? Therefore I propose one of:

    1. If you want to do execute only one migration and only once, simply copy the migration file to your migrations folder

    2. If the two migrations folders are evolving side by side and you would like to automatically run migrations from both directories, you can invoke ecto.migrate twice:

      mix ecto.migrate --migrations-path priv/repo/migrations
      mix ecto.migrate --migrations-path other/app/priv/repo/migrations
      
    3. If the two migrations folders are evolving side by side and you would like to manually run migrations from both directories, you can copy the migrations from one directory to the other and keep only one directory as source of truth