I am using elixir releases to deploy my app to digital ocean. I need to run my migrations so that I can setup my tables in postgres. I followed the directions listed in the Phoenix docs related to ecto migrations and custom commands. However when I attempt to run the command (replacing my_app with the name of my app): _build/prod/rel/my_app/bin/my_app eval "MyApp.Release.migrate" I get this error:
** (RuntimeError) SSL connection can not be established because `:ssl` application is not started,
you can add it to `extra_application` in your `mix.exs`:
def application do
[extra_applications: [:ssl]]
end
(postgrex) lib/postgrex.ex:538: Postgrex.ensure_deps_started!/1
(postgrex) lib/postgrex.ex:480: Postgrex.child_spec/1
(ecto_sql) lib/ecto/adapters/sql.ex:459: Ecto.Adapters.SQL.init/3
(ecto) lib/ecto/repo/supervisor.ex:162: Ecto.Repo.Supervisor.init/1
(stdlib) supervisor.erl:295: :supervisor.init/1
(stdlib) gen_server.erl:374: :gen_server.init_it/2
(stdlib) gen_server.erl:342: :gen_server.init_it/6
(stdlib) proc_lib.erl:249: :proc_lib.init_p_do_apply/3
Following the advice of the error I update my mix.exs file.
def application do
[
mod: {MyApp.Application, []},
extra_applications: [:logger, :runtime_tools, :ssl]
]
en
I run MIX_ENV=prod mix compile, then MIX_ENV=prod mix release, then _build/prod/rel/my_app/bin/my_app eval "MyApp.Release.migrate" again and I still get the same error above related to not having the :ssl application started.
I sense I am missing something but I don’t quite know what it is. Any help is greatly appreciated.
What I reckon happens is that the migration file is run by the eval command outside the normal application startup system (or rather, without it). So it doesn’t load or start what is defined in mix.exs. As you can see in the code, it loads your application manually, and it uses Ecto.Migrator.with_repo/3 that manually starts the Ecto repo(s). So adding :ssl to mix.exs won’t help.
Instead you could use Application.ensure_started(:ssl) at the top of your migration and rollback functions and see if that helps.
This is the correct solution. Once I put Application.ensure_all_started(@app) I was able to run my migrations without error. Now I will need to figure out what that does haha.
Note that Application.ensure_all_started/1 will also start your application, so since it’s a Phoenix app it will start the whole server and any other child processes you have specified in your supervisor. You might not want to do that when running a migration, so you could try just Application.ensure_started/1 to selectively start only the apps you need.
Did you ever get it to work with Application.ensure_started/1? I tried Application.ensure_started(:ssl) and Application.ensure_started(@app) and neither worked. Only Application.ensure_all_started(@app) worked.
If you use Application.ensure_started/1 you will need to figure out and start dependencies of that application on your own. If though you do Application.ensure_all_started/1 the BEAM will figure out dependencies for you and start them.
Therefore using Application.ensure_all_started/1 should be totally fine. Unless you call it with your application, or an application that depends on yours, it shouldn’t start your application.
defmodule Foo.Release do
@app :foo
def migrate do
ensure_started()
for repo <- repos() do
{:ok, _, _} = Ecto.Migrator.with_repo(repo, &Ecto.Migrator.run(&1, :up, all: true))
end
end
def rollback(repo, version) do
ensure_started()
{:ok, _, _} = Ecto.Migrator.with_repo(repo, &Ecto.Migrator.run(&1, :down, to: version))
end
defp repos do
Application.load(@app)
Application.fetch_env!(@app, :ecto_repos)
end
defp ensure_started do
Application.ensure_all_started(:ssl)
end
end