From 3d374bf7df6a5cc4bacefefcb133387fe4c5265f Mon Sep 17 00:00:00 2001 From: rinpatch Date: Sat, 8 Jun 2019 17:15:49 +0300 Subject: [PATCH 01/10] Basic release skeleton --- config/releases.exs | 1 + rel/env.sh.eex | 12 ++++++++++++ rel/pleroma_ctl | 5 +++++ rel/vm.args.eex | 11 +++++++++++ 4 files changed, 29 insertions(+) create mode 100644 config/releases.exs create mode 100644 rel/env.sh.eex create mode 100755 rel/pleroma_ctl create mode 100644 rel/vm.args.eex diff --git a/config/releases.exs b/config/releases.exs new file mode 100644 index 000000000..becde7693 --- /dev/null +++ b/config/releases.exs @@ -0,0 +1 @@ +import Config diff --git a/rel/env.sh.eex b/rel/env.sh.eex new file mode 100644 index 000000000..a4ce25295 --- /dev/null +++ b/rel/env.sh.eex @@ -0,0 +1,12 @@ +#!/bin/sh + +# Sets and enables heart (recommended only in daemon mode) +# if [ "$RELEASE_COMMAND" = "daemon" ] || [ "$RELEASE_COMMAND" = "daemon_iex" ]; then +# HEART_COMMAND="$RELEASE_ROOT/bin/$RELEASE_NAME $RELEASE_COMMAND" +# export HEART_COMMAND +# export ELIXIR_ERL_OPTIONS="-heart" +# fi + +# Set the release to work across nodes +export RELEASE_DISTRIBUTION=name +export RELEASE_NODE=<%= @release.name %>@127.0.0.1 diff --git a/rel/pleroma_ctl b/rel/pleroma_ctl new file mode 100755 index 000000000..543b742b9 --- /dev/null +++ b/rel/pleroma_ctl @@ -0,0 +1,5 @@ +#!/bin/sh +# XXX: This should be removed when elixir's releases get custom command support +SCRIPT=$(readlink -f "$0") +SCRIPTPATH=$(dirname "$SCRIPT") +$SCRIPTPATH/pleroma eval 'Pleroma.ReleaseTasks.mix_task("'"$*"'")' diff --git a/rel/vm.args.eex b/rel/vm.args.eex new file mode 100644 index 000000000..71e803264 --- /dev/null +++ b/rel/vm.args.eex @@ -0,0 +1,11 @@ +## Customize flags given to the VM: http://erlang.org/doc/man/erl.html +## -mode/-name/-sname/-setcookie are configured via env vars, do not set them here + +## Number of dirty schedulers doing IO work (file, sockets, etc) +##+SDio 5 + +## Increase number of concurrent ports/sockets +##+Q 65536 + +## Tweak GC to run more often +##-env ERL_FULLSWEEP_AFTER 10 From c47dc0de2c567195206523a057c7df067d6fb076 Mon Sep 17 00:00:00 2001 From: rinpatch Date: Sat, 8 Jun 2019 17:17:10 +0300 Subject: [PATCH 02/10] Load ex_syslog and copy pleroma_ctl --- mix.exs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/mix.exs b/mix.exs index 9447a2e4f..a6481bab6 100644 --- a/mix.exs +++ b/mix.exs @@ -32,10 +32,22 @@ def project do ], main: "readme", output: "priv/static/doc" + ], + releases: [ + pleroma: [ + include_executables_for: [:unix], + applications: [ex_syslogger: :load, syslog: :load], + steps: [:assemble, ©_pleroma_ctl/1] + ] ] ] end + def copy_pleroma_ctl(%{path: target_path} = release) do + File.cp!("./rel/pleroma_ctl", Path.join([target_path, "bin", "pleroma_ctl"])) + release + end + # Configuration for the OTP application. # # Type `mix help compile.app` for more information. From 4b98a7ce4ef4b4e7b74f533e6d6ed343e1b34c48 Mon Sep 17 00:00:00 2001 From: rinpatch Date: Sat, 8 Jun 2019 17:17:28 +0300 Subject: [PATCH 03/10] Set serve_endpoints to true in prod config as setting it in runtime config would cause issues with mix tasks --- config/prod.exs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/config/prod.exs b/config/prod.exs index d0cfd1ac2..cd5cdb087 100644 --- a/config/prod.exs +++ b/config/prod.exs @@ -15,7 +15,8 @@ # which you typically run after static files are built. config :pleroma, Pleroma.Web.Endpoint, http: [port: 4000], - protocol: "http" + protocol: "http", + serve_endpoints: true # Do not print debug messages in production config :logger, level: :info From d7ec0898e5aa7acae463760fd85d1ebf8307b4f9 Mon Sep 17 00:00:00 2001 From: rinpatch Date: Sat, 8 Jun 2019 17:40:40 +0300 Subject: [PATCH 04/10] Make mix tasks work in a release --- lib/mix/tasks/pleroma/common.ex | 54 ++++++++++++++++++++------ lib/mix/tasks/pleroma/instance.ex | 12 +++--- lib/mix/tasks/pleroma/relay.ex | 4 +- lib/mix/tasks/pleroma/uploads.ex | 12 +++--- lib/mix/tasks/pleroma/user.ex | 64 +++++++++++++++---------------- lib/pleroma/release_tasks.ex | 38 ++++++++++++++++++ rel/pleroma_ctl | 2 +- 7 files changed, 128 insertions(+), 58 deletions(-) create mode 100644 lib/pleroma/release_tasks.ex diff --git a/lib/mix/tasks/pleroma/common.ex b/lib/mix/tasks/pleroma/common.ex index 25977f656..0e03a7872 100644 --- a/lib/mix/tasks/pleroma/common.ex +++ b/lib/mix/tasks/pleroma/common.ex @@ -10,19 +10,51 @@ def start_pleroma do end def get_option(options, opt, prompt, defval \\ nil, defname \\ nil) do - Keyword.get(options, opt) || - case Mix.shell().prompt("#{prompt} [#{defname || defval}]") do - "\n" -> - case defval do - nil -> get_option(options, opt, prompt, defval) - defval -> defval - end - - opt -> - opt |> String.trim() - end + Keyword.get(options, opt) || shell_prompt(prompt, defval, defname) end + def shell_prompt(prompt, defval \\ nil, defname \\ nil) do + prompt_message = "#{prompt} [#{defname || defval}]" + + input = + if mix_shell?(), + do: Mix.shell().prompt(prompt_message), + else: :io.get_line(prompt_message) + + case input do + "\n" -> + case defval do + nil -> + shell_prompt(prompt, defval, defname) + + defval -> + defval + end + + input -> + String.trim(input) + end + end + + def shell_yes?(message) do + shell_prompt(message, "Yn") in ~w(Yn Y y) + end + + def shell_info(message) do + if mix_shell?(), + do: Mix.shell().info(message), + else: IO.puts(message) + end + + def shell_error(message) do + if mix_shell?(), + do: Mix.shell().error(message), + else: IO.puts(:stderr, message) + end + + @doc "Performs a safe check whether `Mix.shell/0` is available (does not raise if Mix is not loaded)" + def mix_shell?, do: :erlang.function_exported(Mix, :shell, 0) + def escape_sh_path(path) do ~S(') <> String.replace(path, ~S('), ~S(\')) <> ~S(') end diff --git a/lib/mix/tasks/pleroma/instance.ex b/lib/mix/tasks/pleroma/instance.ex index 6cee8d630..88925dbaf 100644 --- a/lib/mix/tasks/pleroma/instance.ex +++ b/lib/mix/tasks/pleroma/instance.ex @@ -155,17 +155,17 @@ def run(["gen" | rest]) do dbpass: dbpass ) - Mix.shell().info( + Common.shell_info( "Writing config to #{config_path}. You should rename it to config/prod.secret.exs or config/dev.secret.exs." ) File.write(config_path, result_config) - Mix.shell().info("Writing #{psql_path}.") + Common.shell_info("Writing #{psql_path}.") File.write(psql_path, result_psql) write_robots_txt(indexable) - Mix.shell().info( + Common.shell_info( "\n" <> """ To get started: @@ -179,7 +179,7 @@ def run(["gen" | rest]) do end ) else - Mix.shell().error( + Common.shell_error( "The task would have overwritten the following files:\n" <> (Enum.map(paths, &"- #{&1}\n") |> Enum.join("")) <> "Rerun with `--force` to overwrite them." @@ -204,10 +204,10 @@ defp write_robots_txt(indexable) do if File.exists?(robots_txt_path) do File.cp!(robots_txt_path, "#{robots_txt_path}.bak") - Mix.shell().info("Backing up existing robots.txt to #{robots_txt_path}.bak") + Common.shell_info("Backing up existing robots.txt to #{robots_txt_path}.bak") end File.write(robots_txt_path, robots_txt) - Mix.shell().info("Writing #{robots_txt_path}.") + Common.shell_info("Writing #{robots_txt_path}.") end end diff --git a/lib/mix/tasks/pleroma/relay.ex b/lib/mix/tasks/pleroma/relay.ex index fbec473c5..213ae24d2 100644 --- a/lib/mix/tasks/pleroma/relay.ex +++ b/lib/mix/tasks/pleroma/relay.ex @@ -30,7 +30,7 @@ def run(["follow", target]) do # put this task to sleep to allow the genserver to push out the messages :timer.sleep(500) else - {:error, e} -> Mix.shell().error("Error while following #{target}: #{inspect(e)}") + {:error, e} -> Common.shell_error("Error while following #{target}: #{inspect(e)}") end end @@ -41,7 +41,7 @@ def run(["unfollow", target]) do # put this task to sleep to allow the genserver to push out the messages :timer.sleep(500) else - {:error, e} -> Mix.shell().error("Error while following #{target}: #{inspect(e)}") + {:error, e} -> Common.shell_error("Error while following #{target}: #{inspect(e)}") end end end diff --git a/lib/mix/tasks/pleroma/uploads.ex b/lib/mix/tasks/pleroma/uploads.ex index 106fcf443..8855b5538 100644 --- a/lib/mix/tasks/pleroma/uploads.ex +++ b/lib/mix/tasks/pleroma/uploads.ex @@ -38,10 +38,10 @@ def run(["migrate_local", target_uploader | args]) do Pleroma.Config.put([Upload, :uploader], uploader) end - Mix.shell().info("Migrating files from local #{local_path} to #{to_string(uploader)}") + Common.shell_info("Migrating files from local #{local_path} to #{to_string(uploader)}") if delete? do - Mix.shell().info( + Common.shell_info( "Attention: uploaded files will be deleted, hope you have backups! (--delete ; cancel with ^C)" ) @@ -78,7 +78,7 @@ def run(["migrate_local", target_uploader | args]) do |> Enum.filter(& &1) total_count = length(uploads) - Mix.shell().info("Found #{total_count} uploads") + Common.shell_info("Found #{total_count} uploads") uploads |> Task.async_stream( @@ -90,7 +90,7 @@ def run(["migrate_local", target_uploader | args]) do :ok error -> - Mix.shell().error("failed to upload #{inspect(upload.path)}: #{inspect(error)}") + Common.shell_error("failed to upload #{inspect(upload.path)}: #{inspect(error)}") end end, timeout: 150_000 @@ -99,10 +99,10 @@ def run(["migrate_local", target_uploader | args]) do # credo:disable-for-next-line Credo.Check.Warning.UnusedEnumOperation |> Enum.reduce(0, fn done, count -> count = count + length(done) - Mix.shell().info("Uploaded #{count}/#{total_count} files") + Common.shell_info("Uploaded #{count}/#{total_count} files") count end) - Mix.shell().info("Done!") + Common.shell_info("Done!") end end diff --git a/lib/mix/tasks/pleroma/user.ex b/lib/mix/tasks/pleroma/user.ex index 25fc40ea7..7eaa49836 100644 --- a/lib/mix/tasks/pleroma/user.ex +++ b/lib/mix/tasks/pleroma/user.ex @@ -115,7 +115,7 @@ def run(["new", nickname, email | rest]) do admin? = Keyword.get(options, :admin, false) assume_yes? = Keyword.get(options, :assume_yes, false) - Mix.shell().info(""" + Common.shell_info(""" A user will be created with the following information: - nickname: #{nickname} - email: #{email} @@ -128,7 +128,7 @@ def run(["new", nickname, email | rest]) do - admin: #{if(admin?, do: "true", else: "false")} """) - proceed? = assume_yes? or Mix.shell().yes?("Continue?") + proceed? = assume_yes? or Common.shell_yes?("Continue?") if proceed? do Common.start_pleroma() @@ -145,7 +145,7 @@ def run(["new", nickname, email | rest]) do changeset = User.register_changeset(%User{}, params, need_confirmation: false) {:ok, _user} = User.register(changeset) - Mix.shell().info("User #{nickname} created") + Common.shell_info("User #{nickname} created") if moderator? do run(["set", nickname, "--moderator"]) @@ -159,7 +159,7 @@ def run(["new", nickname, email | rest]) do run(["reset_password", nickname]) end else - Mix.shell().info("User will not be created.") + Common.shell_info("User will not be created.") end end @@ -168,10 +168,10 @@ def run(["rm", nickname]) do with %User{local: true} = user <- User.get_cached_by_nickname(nickname) do User.perform(:delete, user) - Mix.shell().info("User #{nickname} deleted.") + Common.shell_info("User #{nickname} deleted.") else _ -> - Mix.shell().error("No local user #{nickname}") + Common.shell_error("No local user #{nickname}") end end @@ -181,12 +181,12 @@ def run(["toggle_activated", nickname]) do with %User{} = user <- User.get_cached_by_nickname(nickname) do {:ok, user} = User.deactivate(user, !user.info.deactivated) - Mix.shell().info( + Common.shell_info( "Activation status of #{nickname}: #{if(user.info.deactivated, do: "de", else: "")}activated" ) else _ -> - Mix.shell().error("No user #{nickname}") + Common.shell_error("No user #{nickname}") end end @@ -195,7 +195,7 @@ def run(["reset_password", nickname]) do with %User{local: true} = user <- User.get_cached_by_nickname(nickname), {:ok, token} <- Pleroma.PasswordResetToken.create_token(user) do - Mix.shell().info("Generated password reset token for #{user.nickname}") + Common.shell_info("Generated password reset token for #{user.nickname}") IO.puts( "URL: #{ @@ -208,7 +208,7 @@ def run(["reset_password", nickname]) do ) else _ -> - Mix.shell().error("No local user #{nickname}") + Common.shell_error("No local user #{nickname}") end end @@ -216,7 +216,7 @@ def run(["unsubscribe", nickname]) do Common.start_pleroma() with %User{} = user <- User.get_cached_by_nickname(nickname) do - Mix.shell().info("Deactivating #{user.nickname}") + Common.shell_info("Deactivating #{user.nickname}") User.deactivate(user) {:ok, friends} = User.get_friends(user) @@ -224,7 +224,7 @@ def run(["unsubscribe", nickname]) do Enum.each(friends, fn friend -> user = User.get_cached_by_id(user.id) - Mix.shell().info("Unsubscribing #{friend.nickname} from #{user.nickname}") + Common.shell_info("Unsubscribing #{friend.nickname} from #{user.nickname}") User.unfollow(user, friend) end) @@ -233,11 +233,11 @@ def run(["unsubscribe", nickname]) do user = User.get_cached_by_id(user.id) if Enum.empty?(user.following) do - Mix.shell().info("Successfully unsubscribed all followers from #{user.nickname}") + Common.shell_info("Successfully unsubscribed all followers from #{user.nickname}") end else _ -> - Mix.shell().error("No user #{nickname}") + Common.shell_error("No user #{nickname}") end end @@ -274,7 +274,7 @@ def run(["set", nickname | rest]) do end else _ -> - Mix.shell().error("No local user #{nickname}") + Common.shell_error("No local user #{nickname}") end end @@ -284,10 +284,10 @@ def run(["tag", nickname | tags]) do with %User{} = user <- User.get_cached_by_nickname(nickname) do user = user |> User.tag(tags) - Mix.shell().info("Tags of #{user.nickname}: #{inspect(tags)}") + Common.shell_info("Tags of #{user.nickname}: #{inspect(tags)}") else _ -> - Mix.shell().error("Could not change user tags for #{nickname}") + Common.shell_error("Could not change user tags for #{nickname}") end end @@ -297,10 +297,10 @@ def run(["untag", nickname | tags]) do with %User{} = user <- User.get_cached_by_nickname(nickname) do user = user |> User.untag(tags) - Mix.shell().info("Tags of #{user.nickname}: #{inspect(tags)}") + Common.shell_info("Tags of #{user.nickname}: #{inspect(tags)}") else _ -> - Mix.shell().error("Could not change user tags for #{nickname}") + Common.shell_error("Could not change user tags for #{nickname}") end end @@ -326,7 +326,7 @@ def run(["invite" | rest]) do with {:ok, val} <- options[:expires_at], options = Map.put(options, :expires_at, val), {:ok, invite} <- UserInviteToken.create_invite(options) do - Mix.shell().info( + Common.shell_info( "Generated user invite token " <> String.replace(invite.invite_type, "_", " ") ) @@ -340,14 +340,14 @@ def run(["invite" | rest]) do IO.puts(url) else error -> - Mix.shell().error("Could not create invite token: #{inspect(error)}") + Common.shell_error("Could not create invite token: #{inspect(error)}") end end def run(["invites"]) do Common.start_pleroma() - Mix.shell().info("Invites list:") + Common.shell_info("Invites list:") UserInviteToken.list_invites() |> Enum.each(fn invite -> @@ -361,7 +361,7 @@ def run(["invites"]) do " | Max use: #{max_use} Left use: #{max_use - invite.uses}" end - Mix.shell().info( + Common.shell_info( "ID: #{invite.id} | Token: #{invite.token} | Token type: #{invite.invite_type} | Used: #{ invite.used }#{expire_info}#{using_info}" @@ -374,9 +374,9 @@ def run(["revoke_invite", token]) do with {:ok, invite} <- UserInviteToken.find_by_token(token), {:ok, _} <- UserInviteToken.update_invite(invite, %{used: true}) do - Mix.shell().info("Invite for token #{token} was revoked.") + Common.shell_info("Invite for token #{token} was revoked.") else - _ -> Mix.shell().error("No invite found with token #{token}") + _ -> Common.shell_error("No invite found with token #{token}") end end @@ -385,10 +385,10 @@ def run(["delete_activities", nickname]) do with %User{local: true} = user <- User.get_cached_by_nickname(nickname) do {:ok, _} = User.delete_user_activities(user) - Mix.shell().info("User #{nickname} statuses deleted.") + Common.shell_info("User #{nickname} statuses deleted.") else _ -> - Mix.shell().error("No local user #{nickname}") + Common.shell_error("No local user #{nickname}") end end @@ -400,10 +400,10 @@ def run(["toggle_confirmed", nickname]) do message = if user.info.confirmation_pending, do: "needs", else: "doesn't need" - Mix.shell().info("#{nickname} #{message} confirmation.") + Common.shell_info("#{nickname} #{message} confirmation.") else _ -> - Mix.shell().error("No local user #{nickname}") + Common.shell_error("No local user #{nickname}") end end @@ -416,7 +416,7 @@ defp set_moderator(user, value) do {:ok, user} = User.update_and_set_cache(user_cng) - Mix.shell().info("Moderator status of #{user.nickname}: #{user.info.is_moderator}") + Common.shell_info("Moderator status of #{user.nickname}: #{user.info.is_moderator}") user end @@ -429,7 +429,7 @@ defp set_admin(user, value) do {:ok, user} = User.update_and_set_cache(user_cng) - Mix.shell().info("Admin status of #{user.nickname}: #{user.info.is_admin}") + Common.shell_info("Admin status of #{user.nickname}: #{user.info.is_admin}") user end @@ -442,7 +442,7 @@ defp set_locked(user, value) do {:ok, user} = User.update_and_set_cache(user_cng) - Mix.shell().info("Locked status of #{user.nickname}: #{user.info.locked}") + Common.shell_info("Locked status of #{user.nickname}: #{user.info.locked}") user end end diff --git a/lib/pleroma/release_tasks.ex b/lib/pleroma/release_tasks.ex new file mode 100644 index 000000000..66a8b627f --- /dev/null +++ b/lib/pleroma/release_tasks.ex @@ -0,0 +1,38 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.ReleaseTasks do + def run(args) do + [task | args] = String.split(args) + + case task do + "migrate" -> migrate(args) + task -> mix_task(task, args) + end + end + + defp mix_task(task, args) do + # Modules are not loaded before application starts + Mix.Tasks.Pleroma.Common.start_pleroma() + {:ok, modules} = :application.get_key(:pleroma, :modules) + + module = + Enum.find(modules, fn module -> + module = Module.split(module) + + match?(["Mix", "Tasks", "Pleroma" | _], module) and + String.downcase(List.last(module)) == task + end) + + if module do + module.run(args) + else + IO.puts("The task #{task} does not exist") + end + end + + defp migrate(_args) do + :noop + end +end diff --git a/rel/pleroma_ctl b/rel/pleroma_ctl index 543b742b9..16526af44 100755 --- a/rel/pleroma_ctl +++ b/rel/pleroma_ctl @@ -2,4 +2,4 @@ # XXX: This should be removed when elixir's releases get custom command support SCRIPT=$(readlink -f "$0") SCRIPTPATH=$(dirname "$SCRIPT") -$SCRIPTPATH/pleroma eval 'Pleroma.ReleaseTasks.mix_task("'"$*"'")' +$SCRIPTPATH/pleroma eval 'Pleroma.ReleaseTasks.run("'"$*"'")' From 7223c1b643874f368937969be441c42f7eb55d14 Mon Sep 17 00:00:00 2001 From: rinpatch Date: Sat, 8 Jun 2019 20:10:25 +0300 Subject: [PATCH 05/10] Use Mix.shell().yes? if available --- lib/mix/tasks/pleroma/common.ex | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/mix/tasks/pleroma/common.ex b/lib/mix/tasks/pleroma/common.ex index 0e03a7872..7d50605af 100644 --- a/lib/mix/tasks/pleroma/common.ex +++ b/lib/mix/tasks/pleroma/common.ex @@ -37,7 +37,9 @@ def shell_prompt(prompt, defval \\ nil, defname \\ nil) do end def shell_yes?(message) do - shell_prompt(message, "Yn") in ~w(Yn Y y) + if mix_shell?(), + do: Mix.shell().yes?("Continue?"), + else: shell_prompt(message, "Continue?") in ~w(Yn Y y) end def shell_info(message) do From b6d2db42a759354bb21e2385021dfb6acfe29ef2 Mon Sep 17 00:00:00 2001 From: rinpatch Date: Sat, 8 Jun 2019 21:26:00 +0300 Subject: [PATCH 06/10] Fix wrong placement of serve_endpoints --- config/prod.exs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/config/prod.exs b/config/prod.exs index cd5cdb087..adc1c4bb7 100644 --- a/config/prod.exs +++ b/config/prod.exs @@ -15,8 +15,9 @@ # which you typically run after static files are built. config :pleroma, Pleroma.Web.Endpoint, http: [port: 4000], - protocol: "http", - serve_endpoints: true + protocol: "http" + +config :phoenix, serve_endpoints: true # Do not print debug messages in production config :logger, level: :info From 2a659b35f16cacb39ea6dae2aefd3572f4be6783 Mon Sep 17 00:00:00 2001 From: rinpatch Date: Sun, 9 Jun 2019 13:33:44 +0300 Subject: [PATCH 07/10] Add migrate/rollback to release tasks --- lib/pleroma/release_tasks.ex | 36 +++++++++++++++++++++++++++++++----- rel/pleroma_ctl | 20 +++++++++++++++++--- 2 files changed, 48 insertions(+), 8 deletions(-) diff --git a/lib/pleroma/release_tasks.ex b/lib/pleroma/release_tasks.ex index 66a8b627f..7726bc635 100644 --- a/lib/pleroma/release_tasks.ex +++ b/lib/pleroma/release_tasks.ex @@ -3,18 +3,21 @@ # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.ReleaseTasks do + @repo Pleroma.Repo + def run(args) do + Mix.Tasks.Pleroma.Common.start_pleroma() [task | args] = String.split(args) case task do - "migrate" -> migrate(args) + "migrate" -> migrate() + "create" -> create() + "rollback" -> rollback(String.to_integer(Enum.at(args, 0))) task -> mix_task(task, args) end end defp mix_task(task, args) do - # Modules are not loaded before application starts - Mix.Tasks.Pleroma.Common.start_pleroma() {:ok, modules} = :application.get_key(:pleroma, :modules) module = @@ -32,7 +35,30 @@ defp mix_task(task, args) do end end - defp migrate(_args) do - :noop + def migrate do + {:ok, _, _} = Ecto.Migrator.with_repo(@repo, &Ecto.Migrator.run(&1, :up, all: true)) + end + + def rollback(version) do + {:ok, _, _} = Ecto.Migrator.with_repo(@repo, &Ecto.Migrator.run(&1, :down, to: version)) + end + + def create do + case @repo.__adapter__.storage_up(@repo.config) do + :ok -> + IO.puts("The database for #{inspect(@repo)} has been created") + + {:error, :already_up} -> + IO.puts("The database for #{inspect(@repo)} has already been created") + + {:error, term} when is_binary(term) -> + IO.puts(:stderr, "The database for #{inspect(@repo)} couldn't be created: #{term}") + + {:error, term} -> + IO.puts( + :stderr, + "The database for #{inspect(@repo)} couldn't be created: #{inspect(term)}" + ) + end end end diff --git a/rel/pleroma_ctl b/rel/pleroma_ctl index 16526af44..6137f19d3 100755 --- a/rel/pleroma_ctl +++ b/rel/pleroma_ctl @@ -1,5 +1,19 @@ #!/bin/sh # XXX: This should be removed when elixir's releases get custom command support -SCRIPT=$(readlink -f "$0") -SCRIPTPATH=$(dirname "$SCRIPT") -$SCRIPTPATH/pleroma eval 'Pleroma.ReleaseTasks.run("'"$*"'")' +if [ -z "$1" ] || [ "$1" == "help" ]; then + echo "Usage: $(basename "$0") COMMAND [ARGS] + + The known commands are: + + create Create database schema (needs to be executed only once) + migrate Execute database migrations (needs to be done after updates) + rollback Rollback database migrations (needs to be done before downgrading) + + and any mix tasks under Pleroma namespace, for example \`mix pleroma.user COMMAND\` is + equialent to \`$(basename "$0") user COMMAND\` +" +else + SCRIPT=$(readlink -f "$0") + SCRIPTPATH=$(dirname "$SCRIPT") + $SCRIPTPATH/pleroma eval 'Pleroma.ReleaseTasks.run("'"$*"'")' +fi From bf391569cf83c3dec75fe1a6870ae0b9f228400b Mon Sep 17 00:00:00 2001 From: rinpatch Date: Sun, 9 Jun 2019 13:34:58 +0300 Subject: [PATCH 08/10] specify that a version is needed for rollback --- rel/pleroma_ctl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rel/pleroma_ctl b/rel/pleroma_ctl index 6137f19d3..1276bf339 100755 --- a/rel/pleroma_ctl +++ b/rel/pleroma_ctl @@ -5,9 +5,9 @@ if [ -z "$1" ] || [ "$1" == "help" ]; then The known commands are: - create Create database schema (needs to be executed only once) - migrate Execute database migrations (needs to be done after updates) - rollback Rollback database migrations (needs to be done before downgrading) + create Create database schema (needs to be executed only once) + migrate Execute database migrations (needs to be done after updates) + rollback [VERSION] Rollback database migrations (needs to be done before downgrading) and any mix tasks under Pleroma namespace, for example \`mix pleroma.user COMMAND\` is equialent to \`$(basename "$0") user COMMAND\` From cfcc0c87763f460f4f3329f4de64890fbf23e795 Mon Sep 17 00:00:00 2001 From: rinpatch Date: Sun, 9 Jun 2019 13:56:41 +0300 Subject: [PATCH 09/10] Add a changelog entry for releases --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 510ad7ff5..4dafa0df5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - [MongooseIM](https://github.com/esl/MongooseIM) http authentication support. - LDAP authentication - External OAuth provider authentication +- Support for building a release using [`mix release`](https://hexdocs.pm/mix/master/Mix.Tasks.Release.html) - A [job queue](https://git.pleroma.social/pleroma/pleroma_job_queue) for federation, emails, web push, etc. - [Prometheus](https://prometheus.io/) metrics - Support for Mastodon's remote interaction From dbe4c2b7c8cfec4d8348de869a86c03015a7b7c5 Mon Sep 17 00:00:00 2001 From: lain Date: Mon, 10 Jun 2019 11:47:22 +0000 Subject: [PATCH 10/10] Update pleroma_ctl --- rel/pleroma_ctl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rel/pleroma_ctl b/rel/pleroma_ctl index 1276bf339..ef2717c44 100755 --- a/rel/pleroma_ctl +++ b/rel/pleroma_ctl @@ -10,7 +10,7 @@ if [ -z "$1" ] || [ "$1" == "help" ]; then rollback [VERSION] Rollback database migrations (needs to be done before downgrading) and any mix tasks under Pleroma namespace, for example \`mix pleroma.user COMMAND\` is - equialent to \`$(basename "$0") user COMMAND\` + equivalent to \`$(basename "$0") user COMMAND\` " else SCRIPT=$(readlink -f "$0")