Skip to content

Repository files navigation

Hex.pm Version Hex docs License

Data Migration

You're reading the main branch's readme. Please visit hexdocs for the latest published documentation.

View Ecto Data Migrations and run them from a Phoenix LiveDashboard page. Streams logs as the data migrations runs to the dashboard.

For example, in your Phoenix router:

live_dashboard "/my/admin/dashboard",
  # must have `allow_destructive_actions: true` in order to run data migrations
  # otherwise it will be view-only to see the status
  allow_destructive_actions: true,
  # Provide the page with Repo and migration folders config
  additional_pages: [
    # so the route becomes "/my/admin/dashboard/data_migrations"
    data_migrations: {
      DataMigration.LiveDashboard.Page,
      {MyApp.PubSub, %{MyApp.Repo => ["data_migrations"]}, options}
      # These paths will be passed into `Ecto.Migrator.migrations_path(repo, path)`
      # `options` is optional; you may supply 2 item tuple instead to omit options
    }
  ]

Options you may supply to the page:

  • :topic a different PubSub topic to listen to for capturing migration logs.
  • :listen_for_logs A list of MFAs (tuple of length 1, 2, or 3) for which the page to listen for logs. You can also supply a module namespace, eg, MyApp.DataMigration and any module under that namespace will have its logs listened to, eg MyApp.DataMigration.FooBar. By default, the app will listen to Ecto.Adapters.SQL, Ecto.Migration.Runner, and Ecto.Migrator for logs.

Running data migrations by version

DataMigration.pending/2 lists the data migrations that have not run, oldest first, and DataMigration.run/4 runs one by version, and no other:

path = Ecto.Migrator.migrations_path(MyApp.Repo, "data_migrations")

DataMigration.pending(MyApp.Repo, path)
#=> [{20260101120000, "mirror_avatars"}]

DataMigration.run(MyApp.Repo, 20260101120000, path)
#=> :ok

run/4 runs nothing and returns {:error, :not_found} for a version no file has, and {:error, :already_applied} for a one-shot data migration that has run.

One-shot and repeatable data migrations

A data migration is one-shot unless it says otherwise. Mark one that is safe to run again with use DataMigration, repeatable: true in place of use Ecto.Migration:

defmodule MyApp.Repo.DataMigrations.MirrorAvatars do
  use DataMigration, repeatable: true

  def up, do: MyApp.Avatars.mirror_all()
  def down, do: :ok
end

Either kind is pending until it has run once. DataMigration.run/4 runs a repeatable one again, and refuses to run a one-shot one twice. The dashboard page's "Migrate up" still runs a data migration once.

Requires OTP 27+

Screenshots

Migration List

Migration Show

Migration Ran with Logs

Migration Ran with Logs and errors

About

Data Migration runner for Elixir

Resources

Stars

12 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages