_toni
Mix Release. Run seeds.exs file via release binary
Hello,
When one is within the Mix context it’s possible to run
$ mix run priv/repo/seeds.exs
Which will evaluate code like the following into the DB:
#/priv/repo/seeds.exs ---> copied to _build/rel/appname/prod/seeds.exs once release is built
defmodule Seeder do
def start_items do
%Item{}
|> Item.changeset(%{name: Faker.Commerce.product_name()})
|> Repo.insert!()
do
end
Seeder.start_items()
I would like to also run the same script in production from a mix release binary à la
./bin/appname eval "Appname.Release.migrate"
What is the recommended way? I already copied the seeds.exs to overlays so they are located in here
_build/rel/appname/prod/seeds.exs
Thank you!
Marked As Solved
dbell
Code.eval_file/1 will execute an EXS file. That is how I am running migrations via a mix release.
Also Liked
webuhu
I currently use the following in one of my projects:
defmodule MyApp.Release.Seeder do
@moduledoc """
Release tasks for seeds.
"""
require Logger
@app :my_app
@doc """
Seed seeds file for repo.
"""
@spec seed(Ecto.Repo.t(), String.t()) :: :ok | {:error, any()}
def seed(repo, filename) do
load_app()
case Ecto.Migrator.with_repo(repo, &eval_seed(&1, filename)) do
{:ok, {:ok, _fun_return}, _apps} ->
:ok
{:ok, {:error, reason}, _apps} ->
Logger.error(reason)
{:error, reason}
{:error, term} ->
IO.warn(term, [])
{:error, term}
end
end
@spec eval_seed(Ecto.Repo.t(), String.t()) :: any()
defp eval_seed(repo, filename) do
seeds_file = get_path(repo, "seeds", filename)
if File.regular?(seeds_file) do
{:ok, Code.eval_file(seeds_file)}
else
{:error, "Seeds file not found."}
end
end
@spec get_path(Ecto.Repo.t(), String.t(), String.t()) :: String.t()
defp get_path(repo, directory, filename) do
priv_dir = "#{:code.priv_dir(@app)}"
repo_underscore =
repo
|> Module.split()
|> List.last()
|> Macro.underscore()
Path.join([priv_dir, repo_underscore, directory, filename])
end
@spec load_app() :: :ok | {:error, term()}
defp load_app(), do: Application.load(@app)
end
And then for the release:
bin/my_app eval 'MyApp.Release.Seeder.seed(Elixir.MyApp.Repo, "seed.exs")
PS: You probably need to add to your config.exs
config :my_app, MyApp.Repo,
start_apps_before_migration: [:logger]
polypush135
/some_release/bin/prod eval "MyApp.Seeder.start_items"
assuming you are using releases
_toni
Following Deploying with Releases — Phoenix v1.7.10 for migrations I got stuck when it comes to the seeds due to the fact that they by consensus live in a script .exs which I assumed requires the mix tool to the mix runex.
Ah cool. Even better
Can you briefly annotate how that invoking would look like, I did find its full path via priv_dir(:appname) function but didn’t figure out how to run the script itself.
defmodule Appname.Release do
def run_seeds do
# Load seeds.exs script here
end
end
_toni
Thanks @polypush135 @webuhu @mudasobwa I learned from all insights and comments!
Defly @dbell’s answers the original question most straightforwardly though, thx! 







