Help us improve
Share bugs, ideas, or general feedback.
From elixir-dev
Set up database migrations for Elixir releases. Use when asked to configure release migrations, add migrate command to releases, or set up Ecto for production deployment without Mix.
npx claudepluginhub gsmlg-dev/code-agent --plugin elixir-devHow this skill is triggered — by the user, by Claude, or both
Slash command
/elixir-dev:ecto-release-migrationsThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
In Elixir releases, Mix is not available. This skill creates a Release module that handles database creation, migration, and rollback via `bin/app_name eval` commands.
Provides Elixir/Phoenix deployment patterns including runtime.exs for env vars/secrets, Dockerfile, fly.toml, mix releases, rel/ overlays, health checks. Use for Fly.io, Docker, CI/CD, migrations.
Guides Elixir app configuration distinguishing runtime vs compile-time settings using config.exs/runtime.exs, Application.get_env, and env-specific files for apps, releases, libraries.
Guides Elixir application configuration, covering runtime vs compile-time settings, config.exs, runtime.exs, and Application.get_env.
Share bugs, ideas, or general feedback.
In Elixir releases, Mix is not available. This skill creates a Release module that handles database creation, migration, and rollback via bin/app_name eval commands.
Detect app name and repos
mix.exs for app nameconfig/config.exs or config/runtime.exs for Ecto reposCreate Release module
lib/<app_name>/release.exVerify config
config/runtime.exs has production database configDATABASE_URL or explicit configdefmodule <AppName>.Release do
@moduledoc """
Release tasks for database management.
Usage in production:
bin/<app_name> eval "<AppName>.Release.migrate()"
bin/<app_name> eval "<AppName>.Release.rollback(<AppName>.Repo, 20240101000000)"
"""
@app :<app_name>
def migrate do
load_app()
for repo <- repos() do
{:ok, _, _} = Ecto.Migrator.with_repo(repo, &Ecto.Migrator.run(&1, :up, all: true))
end
end
def rollback(repo, version) do
load_app()
{:ok, _, _} = Ecto.Migrator.with_repo(repo, &Ecto.Migrator.run(&1, :down, to: version))
end
def create do
load_app()
for repo <- repos() do
case repo.__adapter__().storage_up(repo.config()) do
:ok -> IO.puts("Database created for #{inspect(repo)}")
{:error, :already_up} -> IO.puts("Database already exists for #{inspect(repo)}")
{:error, term} -> raise "Failed to create database: #{inspect(term)}"
end
end
end
def seed do
load_app()
for repo <- repos() do
{:ok, _, _} = Ecto.Migrator.with_repo(repo, fn _repo ->
seed_file = Application.app_dir(@app, "priv/repo/seeds.exs")
if File.exists?(seed_file) do
Code.eval_file(seed_file)
end
end)
end
end
defp repos do
Application.fetch_env!(@app, :ecto_repos)
end
defp load_app do
Application.ensure_all_started(:ssl)
Application.load(@app)
end
end
If multiple repos exist (e.g., Repo and ReadRepo), ensure config.exs has:
config :<app_name>, ecto_repos: [<AppName>.Repo, <AppName>.ReadRepo]
After creating the module:
mix compilemix run -e "<AppName>.Release.migrate()"MIX_ENV=prod mix release_build/prod/rel/<app_name>/bin/<app_name> eval "<AppName>.Release.migrate()"Add to project README or deployment docs:
# Create database (first deploy only)
bin/<app_name> eval "<AppName>.Release.migrate()"
# Run migrations
bin/<app_name> eval "<AppName>.Release.migrate()"
# Rollback to specific version
bin/<app_name> eval "<AppName>.Release.rollback(<AppName>.Repo, 20240101000000)"
# Seed database
bin/<app_name> eval "<AppName>.Release.seed()"
Application.ensure_all_started(:ssl) is called before repo operationsApplication.load(@app) firstconfig :app_name, ecto_repos: [...] exists