123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196 |
- defmodule Plausible.Release do
- use Plausible
- use Plausible.Repo
- require Logger
- @app :plausible
- @start_apps [
- :ssl,
- :postgrex,
- :ch,
- :ecto
- ]
- def should_be_first_launch? do
- on_ee do
- false
- else
- not (_has_users? = Repo.exists?(Plausible.Auth.User))
- end
- end
- def migrate do
- prepare()
- Enum.each(repos(), &run_migrations_for/1)
- IO.puts("Migrations successful!")
- end
- def pending_migrations do
- prepare()
- IO.puts("Pending migrations")
- IO.puts("")
- Enum.each(repos(), &list_pending_migrations_for/1)
- end
- def seed do
- prepare()
- # Run seed script
- Enum.each(repos(), &run_seeds_for/1)
- # Signal shutdown
- IO.puts("Success!")
- end
- def createdb do
- prepare()
- for repo <- repos() do
- :ok = ensure_repo_created(repo)
- end
- IO.puts("Creation of Db successful!")
- end
- def rollback do
- prepare()
- get_step =
- IO.gets("Enter the number of steps: ")
- |> String.trim()
- |> Integer.parse()
- case get_step do
- {int, _trailing} ->
- Enum.each(repos(), fn repo -> run_rollbacks_for(repo, int) end)
- IO.puts("Rollback successful!")
- :error ->
- IO.puts("Invalid integer")
- end
- end
- def configure_ref_inspector() do
- priv_dir = Application.app_dir(:plausible, "priv/ref_inspector")
- Application.put_env(:ref_inspector, :database_path, priv_dir)
- end
- def configure_ua_inspector() do
- priv_dir = Application.app_dir(:plausible, "priv/ua_inspector")
- Application.put_env(:ua_inspector, :database_path, priv_dir)
- end
- def dump_plans() do
- prepare()
- Repo.delete_all("plans")
- plans =
- Plausible.Billing.Plans.all()
- |> Plausible.Billing.Plans.with_prices()
- |> Enum.map(fn plan ->
- plan = Map.from_struct(plan)
- monthly_cost = plan.monthly_cost && Money.to_decimal(plan.monthly_cost)
- yearly_cost = plan.yearly_cost && Money.to_decimal(plan.yearly_cost)
- {:ok, features} = Plausible.Billing.Ecto.FeatureList.dump(plan.features)
- {:ok, team_member_limit} = Plausible.Billing.Ecto.Limit.dump(plan.team_member_limit)
- plan
- |> Map.drop([:id])
- |> Map.put(:kind, Atom.to_string(plan.kind))
- |> Map.put(:monthly_cost, monthly_cost)
- |> Map.put(:yearly_cost, yearly_cost)
- |> Map.put(:features, features)
- |> Map.put(:team_member_limit, team_member_limit)
- end)
- {count, _} = Repo.insert_all("plans", plans)
- IO.puts("Inserted #{count} plans")
- end
- ##############################
- defp repos do
- Application.fetch_env!(@app, :ecto_repos)
- end
- defp run_seeds_for(repo) do
- # Run the seed script if it exists
- seed_script = seeds_path(repo)
- if File.exists?(seed_script) do
- IO.puts("Running seed script..")
- Code.eval_file(seed_script)
- end
- end
- defp run_migrations_for(repo) do
- IO.puts("Running migrations for #{repo}")
- {:ok, _, _} = Ecto.Migrator.with_repo(repo, &Ecto.Migrator.run(&1, :up, all: true))
- end
- defp list_pending_migrations_for(repo) do
- IO.puts("Listing pending migrations for #{repo}")
- IO.puts("")
- migration_directory = Ecto.Migrator.migrations_path(repo)
- pending =
- repo
- |> Ecto.Migrator.migrations([migration_directory])
- |> Enum.filter(fn {status, _version, _migration} -> status == :down end)
- if pending == [] do
- IO.puts("No pending migrations")
- else
- Enum.each(pending, fn {_, version, migration} ->
- IO.puts("* #{version}_#{migration}")
- end)
- end
- IO.puts("")
- end
- defp ensure_repo_created(repo) do
- IO.puts("create #{inspect(repo)} database if it doesn't exist")
- case repo.__adapter__.storage_up(repo.config) do
- :ok -> :ok
- {:error, :already_up} -> :ok
- {:error, term} -> {:error, term}
- end
- end
- defp run_rollbacks_for(repo, step) do
- app = Keyword.get(repo.config, :otp_app)
- IO.puts("Running rollbacks for #{app} (STEP=#{step})")
- {:ok, _, _} =
- Ecto.Migrator.with_repo(repo, &Ecto.Migrator.run(&1, :down, all: false, step: step))
- end
- defp prepare do
- IO.puts("Loading #{@app}..")
- # Load the code for myapp, but don't start it
- :ok = Application.ensure_loaded(@app)
- IO.puts("Starting dependencies..")
- # Start apps necessary for executing migrations
- Enum.each(@start_apps, &Application.ensure_all_started/1)
- # Start the Repo(s) for myapp
- IO.puts("Starting repos..")
- Enum.each(repos(), & &1.start_link(pool_size: 2))
- end
- defp seeds_path(repo), do: priv_path_for(repo, "seeds.exs")
- defp priv_path_for(repo, filename) do
- app = Keyword.get(repo.config, :otp_app)
- IO.puts("App: #{app}")
- repo_underscore = repo |> Module.split() |> List.last() |> Macro.underscore()
- Path.join([priv_dir(app), repo_underscore, filename])
- end
- defp priv_dir(app), do: "#{:code.priv_dir(app)}"
- end
|