Check for unapplied migrations on startup
authorrinpatch <rinpatch@sdf.org>
Thu, 16 Jan 2020 16:01:31 +0000 (19:01 +0300)
committerrinpatch <rinpatch@sdf.org>
Mon, 20 Jan 2020 09:20:26 +0000 (12:20 +0300)
Closes #1328

CHANGELOG.md
lib/pleroma/application.ex
lib/pleroma/repo.ex
test/repo_test.exs

index 182f5e579add447127e27d6d6b940f200fcc688b..af497dcbabf0042450f9bb5781e36b08c1a77737 100644 (file)
@@ -10,6 +10,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 - **Breaking**: MDII uploader
 
 ### Changed
 - **Breaking**: MDII uploader
 
 ### Changed
+- **Breaking:** Pleroma won't start if it detects unapplied migrations
 - **Breaking:** attachments are removed along with statuses when there are no other references to it
 - **Breaking:** Elixir >=1.8 is now required (was >= 1.7)
 - **Breaking:** attachment links (`config :pleroma, :instance, no_attachment_links` and `config :pleroma, Pleroma.Upload, link_name`) disabled by default
 - **Breaking:** attachments are removed along with statuses when there are no other references to it
 - **Breaking:** Elixir >=1.8 is now required (was >= 1.7)
 - **Breaking:** attachment links (`config :pleroma, :instance, no_attachment_links` and `config :pleroma, Pleroma.Upload, link_name`) disabled by default
index 2ae052069da301d0032579b6a282f5bd7e40d5e9..e1706887671fab475c6cd8517e05071c9091cc37 100644 (file)
@@ -33,6 +33,7 @@ defmodule Pleroma.Application do
   def start(_type, _args) do
     Pleroma.HTML.compile_scrubbers()
     Pleroma.Config.DeprecationWarnings.warn()
   def start(_type, _args) do
     Pleroma.HTML.compile_scrubbers()
     Pleroma.Config.DeprecationWarnings.warn()
+    Pleroma.Repo.check_migrations_applied!()
     setup_instrumenters()
     load_custom_modules()
 
     setup_instrumenters()
     load_custom_modules()
 
index f57e088bc288f321c11c62868ea5b363d77a702b..cb0b6653cd465bb361201ebd0dfb0d0f475f9b2f 100644 (file)
@@ -8,6 +8,8 @@ defmodule Pleroma.Repo do
     adapter: Ecto.Adapters.Postgres,
     migration_timestamps: [type: :naive_datetime_usec]
 
     adapter: Ecto.Adapters.Postgres,
     migration_timestamps: [type: :naive_datetime_usec]
 
+  require Logger
+
   defmodule Instrumenter do
     use Prometheus.EctoInstrumenter
   end
   defmodule Instrumenter do
     use Prometheus.EctoInstrumenter
   end
@@ -47,4 +49,37 @@ defmodule Pleroma.Repo do
       _ -> {:error, :not_found}
     end
   end
       _ -> {:error, :not_found}
     end
   end
+
+  def check_migrations_applied!() do
+    unless Pleroma.Config.get(
+             [:i_am_aware_this_may_cause_data_loss, :disable_migration_check],
+             false
+           ) do
+      Ecto.Migrator.with_repo(__MODULE__, fn repo ->
+        down_migrations =
+          Ecto.Migrator.migrations(repo)
+          |> Enum.reject(fn
+            {:up, _, _} -> true
+            {:down, _, _} -> false
+          end)
+
+        if length(down_migrations) > 0 do
+          down_migrations_text =
+            Enum.map(down_migrations, fn {:down, id, name} -> "- #{name} (#{id})\n" end)
+
+          Logger.error(
+            "The following migrations were not applied:\n#{down_migrations_text}If you want to start Pleroma anyway, set\nconfig :pleroma, :i_am_aware_this_may_cause_data_loss, disable_migration_check: true"
+          )
+
+          raise Pleroma.Repo.UnappliedMigrationsError
+        end
+      end)
+    else
+      :ok
+    end
+  end
+end
+
+defmodule Pleroma.Repo.UnappliedMigrationsError do
+  defexception message: "Unapplied Migrations detected"
 end
 end
index 85b64d4d152d6e684df9aae5d4d98564e6afccd8..5526b03272b321c6c592b77a7f09528d8e652009 100644 (file)
@@ -4,7 +4,10 @@
 
 defmodule Pleroma.RepoTest do
   use Pleroma.DataCase
 
 defmodule Pleroma.RepoTest do
   use Pleroma.DataCase
+  import ExUnit.CaptureLog
   import Pleroma.Factory
   import Pleroma.Factory
+  import Mock
+
   alias Pleroma.User
 
   describe "find_resource/1" do
   alias Pleroma.User
 
   describe "find_resource/1" do
@@ -46,4 +49,44 @@ defmodule Pleroma.RepoTest do
       assert Repo.get_assoc(token, :user) == {:error, :not_found}
     end
   end
       assert Repo.get_assoc(token, :user) == {:error, :not_found}
     end
   end
+
+  describe "check_migrations_applied!" do
+    setup_with_mocks([
+      {Ecto.Migrator, [],
+       [
+         with_repo: fn repo, fun -> passthrough([repo, fun]) end,
+         migrations: fn Pleroma.Repo ->
+           [
+             {:up, 20_191_128_153_944, "fix_missing_following_count"},
+             {:up, 20_191_203_043_610, "create_report_notes"},
+             {:down, 20_191_220_174_645, "add_scopes_to_pleroma_feo_auth_records"}
+           ]
+         end
+       ]}
+    ]) do
+      :ok
+    end
+
+    test "raises if it detects unapplied migrations" do
+      assert_raise Pleroma.Repo.UnappliedMigrationsError, fn ->
+        capture_log(&Repo.check_migrations_applied!/0)
+      end
+    end
+
+    test "doesn't do anything if disabled" do
+      disable_migration_check =
+        Pleroma.Config.get([:i_am_aware_this_may_cause_data_loss, :disable_migration_check])
+
+      Pleroma.Config.put([:i_am_aware_this_may_cause_data_loss, :disable_migration_check], true)
+
+      on_exit(fn ->
+        Pleroma.Config.put(
+          [:i_am_aware_this_may_cause_data_loss, :disable_migration_check],
+          disable_migration_check
+        )
+      end)
+
+      assert :ok == Repo.check_migrations_applied!()
+    end
+  end
 end
 end