forked from plausible/analytics
-
Notifications
You must be signed in to change notification settings - Fork 0
/
plausible_release.ex
157 lines (125 loc) · 4.11 KB
/
plausible_release.ex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
defmodule Plausible.Release do
use Plausible.Repo
@app :plausible
@start_apps [
:postgrex,
:clickhousex,
:ecto
]
def init_admin do
prepare()
{admin_email, admin_user, admin_pwd} =
validate_admin(
{Application.get_env(:plausible, :admin_email),
Application.get_env(:plausible, :admin_user),
Application.get_env(:plausible, :admin_pwd)}
)
case Plausible.Auth.find_user_by(email: admin_email) do
nil ->
{:ok, _} = Plausible.Auth.create_user(admin_user, admin_email, admin_pwd)
IO.puts("Admin user created successful!")
_ ->
IO.puts("Admin user already exists. I won't override, bailing")
end
end
def migrate do
prepare()
Enum.each(repos(), &run_migrations_for/1)
IO.puts("Migrations successful!")
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
##############################
defp validate_admin({nil, nil, nil}) do
random_user = :crypto.strong_rand_bytes(8) |> Base.encode64() |> binary_part(0, 8)
random_pwd = :crypto.strong_rand_bytes(20) |> Base.encode64() |> binary_part(0, 20)
random_email = "#{random_user}@#{System.get_env("HOST")}"
IO.puts("generated admin user/password: #{random_email} / #{random_pwd}")
{random_email, random_user, random_pwd}
end
defp validate_admin({admin_email, admin_user, admin_password}) do
{admin_email, admin_user, admin_password}
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 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.load(@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