meraj
Running ecto migration via release from distillery
I have an elixir umbrella project with three applications. I am creating its binary (release) via distillery.
Running this command creates .tar.gz file in _build/prod/rel/se/releases/0.1.0:
MIX_ENV=prod mix release --env=qa
And I am able to extract and run the application. To run ecto migration I have added this module for release tasks [by following https://hexdocs.pm/distillery/running-migrations.html ]:
defmodule Se.ReleaseTasks do
@start_apps [
:postgrex,
:ecto
]
def myapp, do: Application.get_application(__MODULE__)
def repos, do: Application.get_env(myapp(), :ecto_repos, [])
def seed() do
me = myapp()
IO.puts "Loading #{me}.."
# Load the code for myapp, but don't start it
:ok = Application.load(me)
IO.puts "Starting dependencies.."
# Start apps necessary for executing migrations
Enum.each(@start_apps, &Application.ensure_all_started/1)
# Start the Repo(s) for myapp
IO.puts "Starting repos.."
Enum.each(repos(), &(&1.start_link(pool_size: 1)))
# Run migrations
migrate()
# Run seed script
Enum.each(repos(), &run_seeds_for/1)
# Signal shutdown
IO.puts "Success!"
:init.stop()
end
def migrate, do: Enum.each(repos(), &run_migrations_for/1)
def priv_dir(app), do: "#{:code.priv_dir(app)}"
defp run_migrations_for(repo) do
app = Keyword.get(repo.config, :otp_app)
IO.puts "Running migrations for #{app}"
Ecto.Migrator.run(repo, migrations_path(repo), :up, all: true)
end
def run_seeds_for(repo) do
# Run the seed script if it exists
seed_script = seeds_path(repo)
if File.exists?(seed_script) do
IO.puts "Running seed script.."
Code.eval_file(seed_script)
end
end
def migrations_path(repo), do: priv_path_for(repo, "migrations")
def seeds_path(repo), do: priv_path_for(repo, "seeds.exs")
def priv_path_for(repo, filename) do
app = Keyword.get(repo.config, :otp_app)
repo_underscore = repo |> Module.split |> List.last |> Macro.underscore
Path.join([priv_dir(app), repo_underscore, filename])
end
end
Application is run and compiled with this code located in one of the umbrella project where we require migrations. After compilation and starting server, when I try to run it via:
bin/se_cloud command Elixir.Se.ReleaseTasks seed
I get this error:
Elixir.Se.ReleaseTasks.seed is either not defined or has a non-zero arity
Did anyone else encounter this issue? Or I am mis-configuring something here?
Most Liked
idi527
That might be the problem. For some reason this module does not get loaded in your release. What “otp app” do you define this module in? Does that “otp app” get added to the release?
In other words, it seems that your app is named :se (judging by Se). Is :se anywhere in your rel/config.exs?
ndac_todoroki
I got suspicious about Application.get_application. It says
The application is located by analyzing the spec of all loaded applications. Returns nil if the module is not listed in any application spec.
in the docs. So I tried
def myapp do
app = Application.get_application(__MODULE__)
if app do
app
else
loaded_list() |> IO.puts
raise("couldn't get application for #{__MODULE__}.")
end
end
defp loaded_list, do: Application.loaded_applications |> Enum.map(fn {name, dis, ver} -> "#{name}, #{ver}" end) |> Enum.join("\n")
and this gave me
kernel, 5.3
stdlib, 3.4
elixir, 1.6.1
compiler, 7.1
iex, 1.6.1
{"init terminating in do_boot",{#{'__exception__'=>true,'__struct__'=>'Elixir.RuntimeError',message=><<"couldn't get application for......
where when you do the same thing from app console, you get a long list of loaded apps.
So this may mean that if you call the task, the app isn’t loaded, so you can’t do Application.get_application. Maybe this is umbrella-apps specific (if the examples in the docs works on normal phoenix apps)?
jswny
I had the same problem with a normal, non-umbrella Phoenix app so I think it is just broken in general for some reason. It must work for some people though since it is on the Distillery docs but I don’t know why it wouldn’t work for many others.








