Hello there,
I am currently running into an issue with a release task (used to run database migrations after a new release has been deployed). For some reason it throws a noproc error on our server machine, despite working perfectly fine on my machine.
Apparently an application is not running, which does not seem to be true.
I’ll post the script and the output generated by our CD below:
release_tasks.ex
defmodule Sahnee.ReleaseTasks do
@start_apps [
:telemetry,
:postgrex,
:ecto
]
def migrate() do
IO.puts "Loading sahnee ..."
# Load the code for sahnee, but don't start it
:ok = Application.load(:sahnee)
# Start apps necessary for executing migrations
IO.puts "Starting dependencies #{inspect @start_apps} ..."
Enum.each(@start_apps, fn(app) ->
IO.puts " ... application #{app}"
{:ok, _} = Application.ensure_all_started(app)
end)
# Start the Repo(s) for sahnee
IO.puts "Starting repo ..."
Sahnee.Repo.start_link()
all_started = Application.started_applications()
IO.puts "All started applications: #{inspect all_started}"
# Run migrations
run_migrations_for(:sahnee)
# Run the seed script if it exists
seed_script = seed_path(:sahnee)
if File.exists?(seed_script) do
IO.puts "Running seed script ..."
Code.eval_file(seed_script)
end
# Signal shutdown
IO.puts "Success!"
:init.stop()
end
def priv_dir(app), do: "#{:code.priv_dir(app)}"
defp run_migrations_for(app) do
IO.puts "Running migrations for #{app} ..."
Ecto.Migrator.run(Sahnee.Repo, migrations_path(app), :up, all: true)
end
defp migrations_path(app), do: Path.join([priv_dir(app), "repo", "migrations"])
defp seed_path(app), do: Path.join([priv_dir(app), "repo", "seeds.exs"])
end
CD output:
+ ssh sahnee@sahneedestaging.sahnee.internal /opt/sahnee/build/bin/sahnee eval Sahnee.ReleaseTasks.migrate
Loading sahnee ...
Starting dependencies [:telemetry, :postgrex, :ecto] ...
... application telemetry
... application postgrex
... application ecto
Starting repo ...
All started applications: [
{:ecto, 'A toolkit for data mapping and language integrated query for Elixir', '3.2.5'},
{:postgrex, 'PostgreSQL driver for Elixir', '0.15.2'},
{:db_connection, 'Database connection behaviour for database transactions and connection pooling\n', '2.1.1'},
{:decimal, 'Arbitrary precision decimal arithmetic.', '1.8.0'},
{:connection, 'Connection behaviour for connection processes\n', '1.0.4'},
{:crypto, 'CRYPTO', '4.6.5'},
{:telemetry, 'Dynamic dispatching library for metrics and instrumentations', '0.4.1'},
{:logger, 'logger', '1.10.2'},
{:elixir, 'elixir', '1.10.2'},
{:compiler, 'ERTS CXC 138 10', '7.5.3'},
{:stdlib, 'ERTS CXC 138 10', '3.12'},
{:kernel, 'ERTS CXC 138 10', '6.5.2'}
]
Running migrations for sahnee ...
** (exit) exited in: GenServer.call(Ecto.MigratorSupervisor, {:start_child, {{Ecto.Migration.Runner, :start_link, [{#PID<0.292.0>, Sahnee.Repo, Sahnee.Repo.Migrations.User, :forward, :up, %{level: :info, sql: false}}]}, :temporary, 5000, :worker, [Ecto.Migration.Runner]}}, :infinity)
** (EXIT) no process: the process is not alive or there's no process currently associated with the given name, possibly because its application isn't started
(elixir 1.10.2) lib/gen_server.ex:1013: GenServer.call/3
lib/ecto/migration/runner.ex:21: Ecto.Migration.Runner.run/7
lib/ecto/migrator.ex:342: Ecto.Migrator.attempt/7
lib/ecto/migrator.ex:243: anonymous fn/4 in Ecto.Migrator.do_up/4
lib/ecto/migrator.ex:324: anonymous fn/3 in Ecto.Migrator.run_maybe_in_transaction/6
lib/ecto/adapters/sql.ex:898: anonymous fn/3 in Ecto.Adapters.SQL.checkout_or_transaction/4
(db_connection 2.1.1) lib/db_connection.ex:1415: DBConnection.run_transaction/4
lib/ecto/migrator.ex:323: Ecto.Migrator.run_maybe_in_transaction/6
It tries to call Ecto.MigrationSupervisor, which I’d assume should be started by the Ecto application. Do I have to take additional steps to be able to run migrations in a release task?
If I create a release on my machine using MIX_ENV=prod mix release
and then run the release task everything works just fine.
Or is my approach wrong? It seems like a somewhat hacky solution. What is the standard approach to running migrations in a production environment which does not have access to the source code anymore?
Thanks for your time!