We’re Fly.io. We run apps for our users on hardware we host around the world. This post is about how to continue development after you’ve run mix ecto.dump
and deleted old migration files. Fly.io happens to be a great place to run Phoenix applications. Check out how to get started!
Problem
At some point, you or your team decided to cut the dead weight of many old migrations and instead run mix ecto.dump
and generate a priv/repo/structure.sql
file.
Now you want to bootstrap a new staging server, dev environment, or just get setup with a clean database. You have a chicken-and-the-egg problem. Your app can’t boot without some initial DB schema and it doesn’t have the old migrations to do that. Also, you can’t IEx into your running app to execute the SQL because it can’t run without the schema.
Looking for a solution when deploying to a clean database in a production-like environment? Check out this post!
This is the problem we need to solve: How do we continue development an app that relies on a structure.sql
file generated from mix ecto.dump
and we are missing older migrations?
Solution
Thankfully the problem is easy to fix, but the solution isn’t obvious.
Assuming the mix ecto.dump
command was used, we have a priv/repo/structure.sql
file generated for us. That file should be committed to our version control system.
Next, we’ll update our project’s mix.exs
file and tweak the ecto.setup
task. It probably looks something like this: (Reformatted for readability)
defp aliases do
[
# ...
"ecto.setup": [
"ecto.create",
"ecto.migrate",
"run priv/repo/seeds.exs"
],
"ecto.reset": ["ecto.drop", "ecto.setup"],
# ...
]
end
The alias we care about is ecto.setup
.
We’ll add a step between "ecto.create"
and "ecto.migrate"
. We want to call mix ecto.load
. However, we’ll use a couple of the flags to make it safely continue when it detects our schema is already loaded.
The command we want is ecto.load --skip-if-loaded --quiet
. After updating , it should look like this:
"ecto.setup": ["ecto.create", "ecto.load --skip-if-loaded --quiet", "ecto.migrate", "run apps/core/priv/repo/seeds.exs"],
Now when we develop or test against a clean DB, it creates the DB, loads the priv/repo/structure.sql
file into our database, then runs any additional migrations needed before continuing on.
Awesome! We’ve got a slick solution! Problem solved.
Do you need to solve deploying to a clean database in a production-like environment? Check out this post!