DEV: Add a plugin incompatibility message (#8151)

DEV: Add a plugin incompatibility message (#8151)

  • DEV: Add a plugin incompatibility message

  • Extract the plugin_initialization_guard

diff --git a/config/application.rb b/config/application.rb
index b0938cb..dd56bf8 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -21,6 +21,7 @@ require 'action_mailer/railtie'
 require 'sprockets/railtie'
 
 # Plugin related stuff
+require_relative '../lib/plugin_initialization_guard'
 require_relative '../lib/discourse_event'
 require_relative '../lib/discourse_plugin'
 require_relative '../lib/discourse_plugin_registry'
@@ -266,7 +267,9 @@ module Discourse
         Discourse.activate_plugins!
       end
     else
-      Discourse.activate_plugins!
+      plugin_initialization_guard do
+        Discourse.activate_plugins!
+      end
     end
 
     Discourse.find_plugin_js_assets(include_disabled: true).each do |file|
@@ -301,7 +304,9 @@ module Discourse
       OpenID::Util.logger = Rails.logger
 
       # Load plugins
-      Discourse.plugins.each(&:notify_after_initialize)
+      plugin_initialization_guard do
+        Discourse.plugins.each(&:notify_after_initialize)
+      end
 
       # we got to clear the pool in case plugins connect
       ActiveRecord::Base.connection_handler.clear_active_connections!
diff --git a/lib/plugin_initialization_guard.rb b/lib/plugin_initialization_guard.rb
new file mode 100644
index 0000000..a5a164e
--- /dev/null
+++ b/lib/plugin_initialization_guard.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+def plugin_initialization_guard(&block)
+  begin
+    block.call
+  rescue => error
+    plugins_directory = Rails.root + 'plugins'
+
+    plugin_path = error.backtrace_locations.lazy.map do |location|
+      Pathname.new(location.absolute_path)
+        .ascend
+        .lazy
+        .find { |path| path.parent == plugins_directory }
+    end.next
+
+    raise unless plugin_path
+
+    stack_trace = error.backtrace.each_with_index.inject([]) do |messages, (line, index)|
+      if index == 0
+        messages << "#{line}: #{error} (#{error.class})"
+      else
+        messages << "\t#{index}: from #{line}"
+      end
+    end.reverse.join("\n")
+
+    STDERR.puts <<~MESSAGE
+      #{stack_trace}
+
+      ** INCOMPATIBLE PLUGIN **
+
+      You are unable to build Discourse due to errors in the plugin at
+      #{plugin_path}
+
+      Please try removing this plugin and rebuilding again!
+    MESSAGE
+    exit 1
+  end
+end

GitHub sha: 87be6fe9

1 Like