lib/ecto_release_tasks.ex

defmodule SignificaUtils.EctoReleaseTasks do
  @moduledoc """
  Utility function to create release common tasks used in Ecto projects.

  ## Usage

  ```
  defmodule SampleProject.ReleaseTasks do
    use SignificaUtils.EctoReleaseTasks,
      otp_app: :sample_app
  end

  Creates two public functions:

  - `migrate/0`: migrates all the repos to the latest version.
  - `rollback/2`: rolls back the repo to the specified version - `rollback(repo, version)`.

  ```
  """

  defmacro __using__(opts) do
    otp_app = Keyword.fetch!(opts, :otp_app)

    quote do
      def migrate do
        load_app()

        for repo <- get_repos() do
          run_migrations(repo, :up, all: true)
        end
      end

      def rollback(repo, version) do
        load_app()
        run_migrations(repo, :down, to: version)
      end

      defp get_repos do
        Application.fetch_env!(unquote(otp_app), :ecto_repos)
      end

      defp load_app do
        Application.load(unquote(otp_app))
      end

      defp run_migrations(repo, direction, opts \\ []) do
        {:ok, _, _} =
          Ecto.Migrator.with_repo(
            repo,
            &Ecto.Migrator.run(&1, direction, opts)
          )
      end
    end
  end
end