Running all migrations in all children apps from root of umbrella app

I’m working on an umbrella app that has a dozen or so children apps. I really like how the the base config.exs has a simple line that tells the umbrella to load up all of the children’s configs:

import_config "../apps/*/config/config.exs"

I’m wondering how to implement something like that for the various ecto commands, e.g. ecto.migrate ? I would prefer to not have to cd into each app and run migrations separately.

Does someone have an elegant solution for this? Thanks!

I work on an umbrella app and we have a workable solution (I wouldn’t call it elegant). We use it mainly for helping us run the migrations in the test env but you can easily expand it to general migrations.

mix.exs (root):

  defp aliases do
    [
      "test.setup": [
        "cmd MIX_ENV=test mix test.setup"
      ],
    ]
  end

apps/app_one/mix.exs:

  defp aliases do
    [
      "test.setup": ["ecto.create --quiet", "ecto.migrate"]
    ]
  end

apps/app_two/mix.exs:

  defp aliases do
    [
      "test.setup": ["ecto.create --quiet", "ecto.load"]
    ]
  end

apps/app_three/mix.exs:

  defp aliases do
    [
      "test.setup": []
    ]
  end

These are three “types” of different test database setups that we have. Note that the cmd in the root (see mix help cmd) is key here since it is what is cd’ing into each directory for you.

Some warnings:

  • If you run this command before compiling your project you will compile each project with an incomplete set of dependencies and any of your dependencies has code like if Code.ensure_loaded?(Phoenix) do defmodule end then Phoenix may not be detected as not loaded
  • If you don’t use mix cmd (transparently in this case) then the alias in one umbrella project will override the aliases in another project (since the configuration is shared)
1 Like

Interesting. I’m wondering if we could get by with simply enumerating all the necessary seed files in the mix.exs alias. Something like:

defp aliases do
    [
      "ecto.setup": ["ecto.create", "ecto.migrate", 
        "run apps/app_one/priv/repo/seeds.exs",
        "run apps/app_two/priv/repo/seeds.exs",
        "run apps/app_three/priv/repo/seeds.exs",
        # ...
      ],
      "ecto.reset": ["ecto.drop", "ecto.setup"],
      test: ["ecto.create --quiet", "ecto.migrate", "test"],
    ]
end

That seems like it might work in our case…

1 Like

fwiw I just used a Makefile, bit of a hack, but then you can at least automate cd’ing into each app and doing what you need.

1 Like