deprecation_collector 0.5.2 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +9 -0
  3. data/README.md +10 -0
  4. data/deprecation_collector.gemspec +1 -10
  5. data/lib/deprecation_collector/collectors.rb +32 -6
  6. data/lib/deprecation_collector/storage/active_record.rb +155 -0
  7. data/lib/deprecation_collector/storage.rb +6 -1
  8. data/lib/deprecation_collector/version.rb +1 -1
  9. data/lib/deprecation_collector/web/application.rb +6 -5
  10. data/lib/deprecation_collector/web/helpers.rb +18 -11
  11. data/lib/deprecation_collector/web/router.rb +9 -5
  12. data/lib/deprecation_collector/web/views/import.html.slim +12 -0
  13. data/lib/deprecation_collector/web/views/import.html.template.rb +1 -1
  14. data/lib/deprecation_collector/web/views/index.html.slim +121 -0
  15. data/lib/deprecation_collector/web/views/index.html.template.rb +6 -6
  16. data/lib/deprecation_collector/web/views/layout.html.slim +90 -0
  17. data/lib/deprecation_collector/web/views/layout.html.template.rb +1 -1
  18. data/lib/deprecation_collector/web/views/show.html.slim +81 -0
  19. data/lib/deprecation_collector/web/views/show.html.template.rb +2 -2
  20. data/lib/deprecation_collector.rb +13 -3
  21. metadata +7 -43
  22. data/.rspec +0 -3
  23. data/.rubocop.yml +0 -34
  24. data/Appraisals +0 -13
  25. data/Gemfile +0 -33
  26. data/Gemfile.lock +0 -249
  27. data/LICENSE +0 -21
  28. data/Rakefile +0 -30
  29. data/gemfiles/rails_6.gemfile +0 -15
  30. data/gemfiles/rails_6.gemfile.lock +0 -198
  31. data/gemfiles/rails_7.gemfile +0 -15
  32. data/gemfiles/rails_7.gemfile.lock +0 -197
  33. data/gemfiles/rails_none.gemfile +0 -14
  34. data/gemfiles/rails_none.gemfile.lock +0 -62
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 12a18a7dcdd264edfd2e2350b648a5f7ba9ade6c6623ee500ffff557277bc02e
4
- data.tar.gz: 4c39ea72577e7eca7092aa040a9b0095134f833c155b8a417b80be5e6b9a25bf
3
+ metadata.gz: 26bc69b0016762d0f5e8546f48177a7b2d90334bc8f4c995853c51e814386731
4
+ data.tar.gz: d059f4d6985f9136305160d0e0a6ffe184a6ac1a927e31959241e525974d78ea
5
5
  SHA512:
6
- metadata.gz: 0e5acf3561f2b2f106362e3738050197188bd9d51b32c8534feb30ba2bcba67b51ca514a20e529818ac28388b1823371131735adb61ae5e095150908e4542b5e
7
- data.tar.gz: e35978336a7642085f9daca1eff1922d80abd9e769bffef46f6ba6d4c36d066fe99b39f0dba262710c0d8469c7e5f7b9567dc702268d9d4712247ef22dc8f9a1
6
+ metadata.gz: 7a4609b79edbf7f54aa11538a7201595951ced8194d2a65fd01f4ef9be21cc75719fb27c1e0debbfcad5be2fc5407a9e8a04a6b398e7af2bc19c196461017437
7
+ data.tar.gz: 70f742f7dbd0525ee444c5aa076ccd241f1b8b5acd7c20a10b8778e838a40b3ba383dffd2b58b8776da6bc978583775f16104e89db5d1f1746bfe03e6e1ef8a3
data/CHANGELOG.md CHANGED
@@ -1,3 +1,12 @@
1
+ == 0.7.0
2
+ - support for Rails 7.1
3
+ - make install critical section smaller to prevent installation deprecations preventing installation
4
+
5
+ == 0.6.0
6
+ - added active_record storage
7
+ - redis dependency will become optional in v1.0
8
+ - more test coverage
9
+
1
10
  == 0.5.0
2
11
  - more work on ui
3
12
  - refactored to separate deprecations storage from other logic
data/README.md CHANGED
@@ -55,6 +55,16 @@ Rails.application.routes.draw do
55
55
  end
56
56
  ```
57
57
 
58
+ usually it's a good idea to secure the ui in some way, you can use rails route constraint (actual check will depend on your app):
59
+ ```ruby
60
+ Rails.application.routes.draw do
61
+ constraints(->(request) { request.session[:admin] }) do
62
+ require 'deprecation_collector/web'
63
+ mount DeprecationCollector::Web => '/deprecations', as: :deprecations
64
+ end
65
+ end
66
+ ```
67
+
58
68
  ## Development
59
69
 
60
70
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -18,17 +18,8 @@ Gem::Specification.new do |spec|
18
18
  spec.metadata["source_code_uri"] = "https://github.com/Vasfed/deprecation_collector"
19
19
  spec.metadata["changelog_uri"] = "https://github.com/Vasfed/deprecation_collector/blob/main/CHANGELOG.md"
20
20
 
21
- # Specify which files should be added to the gem when it is released.
22
- # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
23
- spec.files = Dir.chdir(File.expand_path(__dir__)) do
24
- `git ls-files -z`.split("\x0").reject do |f|
25
- (f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|travis|circleci)|appveyor)}) ||
26
- f.match(%r{\Alib/deprecation_collector/web/views/.+\.slim\z})
27
- end
28
- end + Dir["lib/deprecation_collector/web/views/*.slim"].map { |template| template.sub(/\.slim\z/, ".template.rb") }
21
+ spec.files = Dir["lib/**/*", "sig/**/*", "*.md", "*.txt", "*.gemspec"].select { |filename| File.file?(filename) }
29
22
  spec.require_paths = ["lib"]
30
23
 
31
24
  spec.add_dependency "redis", ">= 3.0"
32
- spec.add_development_dependency "appraisal"
33
- spec.add_development_dependency "rack-test"
34
25
  end
@@ -2,6 +2,27 @@
2
2
 
3
3
  # :nodoc:
4
4
  class DeprecationCollector
5
+ ACTIVE_SUPPORT_BEHAVIORS = {
6
+ rails71: ->(message, callstack, deprecator) do
7
+ # TODO: use deprecator.gem_name, deprecator.deprecation_horizon
8
+ DeprecationCollector.collect(message, callstack, :rails)
9
+ ActiveSupport::Deprecation::DEFAULT_BEHAVIORS[stock_activesupport_behavior].call(message, callstack, deprecator)
10
+ end,
11
+ legacy: ->(message, callstack, deprecation_horizon, gem_name) do
12
+ DeprecationCollector.collect(message, callstack, :rails)
13
+ ActiveSupport::Deprecation::DEFAULT_BEHAVIORS[stock_activesupport_behavior].call(
14
+ message, callstack, deprecation_horizon, gem_name
15
+ )
16
+ end
17
+ }.freeze
18
+
19
+ # for intercepting deprecations from deprecators not installed in Rails.application.deprecators
20
+ module ActiveSupportDeprecationCollectionPatch
21
+ def behavior
22
+ @behavior ||= [DeprecationCollector::ACTIVE_SUPPORT_BEHAVIORS[:rails71]]
23
+ end
24
+ end
25
+
5
26
  class << self
6
27
  protected
7
28
 
@@ -18,12 +39,17 @@ class DeprecationCollector
18
39
 
19
40
  def tap_activesupport
20
41
  # TODO: a more polite hook
21
- ActiveSupport::Deprecation.behavior = lambda do |message, callstack, deprecation_horizon, gem_name|
22
- # not polite to turn off all other possible behaviors, but otherwise may get duplicate calls
23
- DeprecationCollector.collect(message, callstack, :rails)
24
- ActiveSupport::Deprecation::DEFAULT_BEHAVIORS[stock_activesupport_behavior].call(
25
- message, callstack, deprecation_horizon, gem_name
26
- )
42
+ # not polite to turn off all other possible behaviors, but otherwise may get duplicate calls
43
+ if Rails.respond_to?(:gem_version) && Rails.gem_version >= "7.1"
44
+ Rails.application.deprecators.behavior = ACTIVE_SUPPORT_BEHAVIORS[:rails71] if Rails.application&.deprecators
45
+ # Rails.application.deprecators.behavior only captures new-style deprecations, but we need all:
46
+ if ActiveSupport::Deprecation.respond_to?(:_instance)
47
+ ActiveSupport::Deprecation._instance.behavior = ACTIVE_SUPPORT_BEHAVIORS[:rails71]
48
+ end
49
+ # collect deprecations from deprecators that are not installed in `Rails.application.deprecators`
50
+ ActiveSupport::Deprecation.prepend(ActiveSupportDeprecationCollectionPatch)
51
+ else
52
+ ActiveSupport::Deprecation.behavior = ACTIVE_SUPPORT_BEHAVIORS[:legacy]
27
53
  end
28
54
  end
29
55
 
@@ -0,0 +1,155 @@
1
+ # frozen_string_literal: true
2
+
3
+ class DeprecationCollector
4
+ module Storage
5
+ # NB: this will not work in tests because of transactions, and may be affected by transactions of the app
6
+ # TODO: use separate db connection to mitigate this
7
+ class ActiveRecord < DeprecationCollector::Storage::Base
8
+ def initialize(model: nil, mutex: nil, count: false, write_interval: 900, write_interval_jitter: 60,
9
+ key_prefix: nil)
10
+ super
11
+ raise "key prefix not supported in AR" if key_prefix && key_prefix != "deprecations"
12
+
13
+ self.model = model if model
14
+ @last_write_time = current_time
15
+ @count = count
16
+ @write_interval = write_interval
17
+ @write_interval_jitter = write_interval_jitter
18
+ # on cruby hash itself is threadsafe, but we need to prevent races
19
+ @deprecations_mutex = mutex || Mutex.new
20
+ @deprecations = {}
21
+ @known_digests = Set.new
22
+ end
23
+
24
+ def model=(model)
25
+ expected_class_methods = %i[column_names where pluck delete_all upsert_all find_in_batches find_by]
26
+ unless expected_class_methods.all? { |method_name| model.respond_to?(method_name) }
27
+ raise ArgumentError, "model expected to be a AR-like class responding to #{expected_class_methods.join(', ')}"
28
+ end
29
+
30
+ expected_fields = %w[digest data notes created_at updated_at]
31
+ unless expected_fields.all? { |column_name| model.column_names.include?(column_name) }
32
+ raise ArgumentError, "model expected to be a AR-like class with fields #{expected_fields.join(', ')}"
33
+ end
34
+
35
+ @model = model
36
+ end
37
+
38
+ def model
39
+ @model ||= ::Deprecation
40
+ end
41
+
42
+ attr_writer :key_prefix
43
+
44
+ def unsent_deprecations
45
+ @deprecations
46
+ end
47
+
48
+ def delete(remove_digests)
49
+ model.where(digest: remove_digests).delete_all
50
+ end
51
+
52
+ def clear(enable: false) # rubocop:disable Lint/UnusedMethodArgument
53
+ model.delete_all
54
+ @known_digests.clear
55
+ @deprecations.clear
56
+ end
57
+
58
+ def fetch_known_digests
59
+ @known_digests.merge(model.pluck(:digest))
60
+ end
61
+
62
+ def store(deprecation)
63
+ fresh = !@deprecations.key?(deprecation.digest)
64
+ @deprecations_mutex.synchronize do
65
+ (@deprecations[deprecation.digest] ||= deprecation).touch
66
+ end
67
+
68
+ flush if current_time - @last_write_time > (@write_interval + rand(@write_interval_jitter))
69
+ fresh
70
+ end
71
+
72
+ def flush(force: false)
73
+ return unless force || (current_time > @last_write_time + @write_interval)
74
+
75
+ deprecations_to_flush = nil
76
+ @deprecations_mutex.synchronize do
77
+ deprecations_to_flush = @deprecations
78
+ @deprecations = {}
79
+ @last_write_time = current_time
80
+ # checking in this section to prevent multiple parallel check requests
81
+ return DeprecationCollector.instance.instance_variable_set(:@enabled, false) unless enabled?
82
+ end
83
+
84
+ # write_count_to_redis(deprecations_to_flush) if @count
85
+
86
+ # make as few writes as possible, other workers may already have reported our warning
87
+ fetch_known_digests
88
+ deprecations_to_flush.reject! { |digest, _val| @known_digests.include?(digest) }
89
+ return unless deprecations_to_flush.any?
90
+
91
+ @known_digests.merge(deprecations_to_flush.keys)
92
+
93
+ model.upsert_all(
94
+ deprecations_to_flush.map do |key, deprecation|
95
+ {
96
+ digest: key, data: deprecation.as_json,
97
+ created_at: timestamp_to_time(deprecation.first_timestamp),
98
+ updated_at: timestamp_to_time(deprecation.first_timestamp)
99
+ }
100
+ end,
101
+ unique_by: :digest # , update_only: %i[data updated_at] # rails 7
102
+ )
103
+ end
104
+
105
+ def read_each
106
+ model.find_in_batches do |batch| # this is find_each, but do not require it to be implemented
107
+ batch.each do |record|
108
+ yield(record.digest, record.data.to_json, record.data&.dig("count"), record.notes)
109
+ end
110
+ end
111
+ end
112
+
113
+ def read_one(digest)
114
+ return [nil] * 4 unless (record = model.find_by(digest: digest))
115
+
116
+ [record.digest, record.data.to_json, record.data&.dig("count"), record.notes]
117
+ end
118
+
119
+ def import(dump_hash)
120
+ attrs = dump_hash.map do |key, deprecation|
121
+ time = deprecation["first_timestamp"] || deprecation[:first_timestamp]
122
+ time = time&.yield_self { |tme| timestamp_to_time(tme) } || current_time
123
+ { digest: key, data: deprecation, created_at: time, updated_at: time }
124
+ end
125
+ model.upsert_all(attrs, unique_by: :digest) # , update_only: %i[data updated_at])
126
+ end
127
+
128
+ def cleanup(&_block)
129
+ removed = total = 0
130
+
131
+ model.find_in_batches do |batch|
132
+ total += batch.size
133
+ removed += delete(
134
+ batch.select { |record| yield(record.data.deep_symbolize_keys) }.map(&:digest)
135
+ )
136
+ end
137
+ "#{removed} removed, #{total - removed} left"
138
+ end
139
+
140
+ protected
141
+
142
+ def current_time
143
+ return Time.zone.now if Time.respond_to?(:zone) && Time.zone
144
+
145
+ Time.now
146
+ end
147
+
148
+ def timestamp_to_time(timestamp)
149
+ return Time.zone.at(timestamp) if Time.respond_to?(:zone) && Time.zone
150
+
151
+ Time.at(timestamp)
152
+ end
153
+ end
154
+ end
155
+ end
@@ -21,6 +21,11 @@ class DeprecationCollector
21
21
  def flush(**); end
22
22
 
23
23
  def store(_deprecation); raise("Not implemented"); end
24
+
25
+ def read_each; end
26
+ def read_one(_digest); [nil] * 4 end
27
+
28
+ def import(_dump); end
24
29
  # rubocop:enable Style/SingleLineMethods
25
30
  end
26
31
 
@@ -36,7 +41,7 @@ class DeprecationCollector
36
41
  attr_accessor :write_interval, :write_interval_jitter, :redis, :count
37
42
 
38
43
  def initialize(redis: nil, mutex: nil, count: false, write_interval: 900, write_interval_jitter: 60,
39
- key_prefix: nil)
44
+ key_prefix: nil)
40
45
  super
41
46
  @key_prefix = key_prefix || "deprecations"
42
47
  @redis = redis
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class DeprecationCollector
4
- VERSION = "0.5.2"
4
+ VERSION = "0.7.0"
5
5
  end
@@ -24,17 +24,17 @@ class DeprecationCollector
24
24
 
25
25
  root do # index
26
26
  @deprecations = collector_instance.read_each.to_a.compact
27
- @deprecations = @deprecations.sort_by { |dep| dep[:message] } unless params[:sort] == "0"
27
+ @deprecations = @deprecations.sort_by { |dep| dep[:message].to_s } unless params[:sort] == "0"
28
28
 
29
29
  if params[:reject]
30
- @deprecations = @deprecations.reject { |dep| dep[:message].match?(Regexp.union(Array(params[:reject]))) }
30
+ @deprecations = @deprecations.reject { |dep| dep[:message]&.match?(Regexp.union(Array(params[:reject]))) }
31
31
  end
32
32
 
33
33
  if params[:realm]
34
- @deprecations = @deprecations.select { |dep| dep[:realm].match?(Regexp.union(Array(params[:realm]))) }
34
+ @deprecations = @deprecations.select { |dep| dep[:realm]&.match?(Regexp.union(Array(params[:realm]))) }
35
35
  end
36
36
 
37
- render slim: "index.html"
37
+ render slim: "index.html", locals: { deprecations: @deprecations }
38
38
  end
39
39
 
40
40
  get "/dump.json" do
@@ -42,12 +42,13 @@ class DeprecationCollector
42
42
  end
43
43
 
44
44
  get "/import" do
45
- return "Import not enabled" unless import_enabled?
45
+ halt 403, "Import not enabled" unless import_enabled?
46
46
 
47
47
  render slim: "import.html"
48
48
  end
49
49
 
50
50
  post "/import" do
51
+ halt 403, "Import not enabled" unless import_enabled?
51
52
  unless env["CONTENT_TYPE"]&.start_with?("multipart/form-data") && params.dig(:file, :tempfile)
52
53
  halt 422, "need multipart json file"
53
54
  end
@@ -14,7 +14,7 @@ class DeprecationCollector
14
14
 
15
15
  def root_path
16
16
  # request.base_url ?
17
- "#{env["SCRIPT_NAME"]}/"
17
+ "#{env['SCRIPT_NAME']}/"
18
18
  end
19
19
 
20
20
  def current_path
@@ -26,7 +26,7 @@ class DeprecationCollector
26
26
  end
27
27
 
28
28
  def deprecation_path(id, format: nil)
29
- ["#{root_path}#{id}", format].compact.join('.')
29
+ ["#{root_path}#{id}", format].compact.join(".")
30
30
  end
31
31
 
32
32
  def enable_deprecations_path
@@ -50,7 +50,10 @@ class DeprecationCollector
50
50
  def trigger_rails_deprecation
51
51
  return unless defined?(ActiveSupport::Deprecation)
52
52
 
53
- -> { ActiveSupport::Deprecation.warn("Test deprecation") } []
53
+ deprecator = ActiveSupport::Deprecation
54
+ deprecator = ActiveSupport::Deprecation.new("0.0", "deprecation_collector") if Rails.gem_version >= "7.1"
55
+
56
+ -> { deprecator.warn("Test deprecation") } []
54
57
  end
55
58
 
56
59
  def current_color_theme
@@ -62,14 +65,16 @@ class DeprecationCollector
62
65
  end
63
66
 
64
67
  def detect_tag(deprecation)
65
- msg = deprecation[:message]
68
+ msg = deprecation[:message].to_s
66
69
  return :kwargs if msg.include?("Using the last argument as keyword parameters is deprecated") ||
67
70
  msg.include?("Passing the keyword argument as the last hash parameter is deprecated")
71
+
72
+ nil
68
73
  end
69
74
 
70
75
  def test_deprecation?(deprecation)
71
- %w[trigger_kwargs_error_warning trigger_rails_deprecation].any? do
72
- |method| deprecation[:message].include?(method)
76
+ %w[trigger_kwargs_error_warning trigger_rails_deprecation].any? do |method|
77
+ deprecation[:message].to_s.include?(method)
73
78
  end
74
79
  end
75
80
 
@@ -82,11 +87,13 @@ class DeprecationCollector
82
87
  tags << deprecation[:realm] if deprecation[:realm] && deprecation[:realm] != "rails"
83
88
  tags.merge(deprecation.dig(:notes, :tags) || [])
84
89
 
85
- tags.to_h do |tag|
86
- next [tag, "bg-success"] if tag == :test
87
-
88
- [tag, "bg-secondary"]
89
- end
90
+ tags.map do |tag|
91
+ if tag == :test
92
+ [tag, "bg-success"]
93
+ else
94
+ [tag, "bg-secondary"]
95
+ end
96
+ end.to_h
90
97
  end
91
98
  end
92
99
  end
@@ -54,7 +54,7 @@ class DeprecationCollector
54
54
  return [
55
55
  404,
56
56
  { "content-type" => "text/plain", "x-cascade" => "pass" },
57
- ["Not Found #{env["REQUEST_METHOD"].inspect} #{env[PATH_INFO].inspect}"]
57
+ ["Not Found #{env['REQUEST_METHOD'].inspect} #{env[PATH_INFO].inspect}"]
58
58
  ]
59
59
  end
60
60
 
@@ -172,18 +172,18 @@ class DeprecationCollector
172
172
  }
173
173
 
174
174
  return [status, { "content-type" => "text/html" }.merge(color_scheme_headers), [html.to_s]] if html
175
+
176
+ nil
175
177
  end
176
178
 
177
179
  VIEW_PATH = "#{__dir__}/views"
178
180
 
179
181
  def render_template(template, &block)
180
182
  template_target = template.gsub(/\.slim\z/, ".template.rb")
181
- template_method_name = "_template_#{template_target.gsub(/[^\w]/, "_")}"
183
+ template_method_name = "_template_#{template_target.gsub(/[^\w]/, '_')}"
182
184
  template_filename = File.join(VIEW_PATH, template_target.to_s)
183
185
 
184
- if ENV["DEPRECATION_COLLECTOR_RELOAD_WEB_TEMPLATES"]
185
- _recompile_template(template, template_filename, template_method_name)
186
- end
186
+ _recompile_template(template, template_filename, template_method_name) if _recompile_enabled?
187
187
 
188
188
  _load_template(template_filename, template_method_name) unless respond_to?(template_method_name)
189
189
 
@@ -202,6 +202,10 @@ class DeprecationCollector
202
202
  ActionContext.class_eval(src, template_filename.gsub(/\.template\.rb\z/, ".slim"), 1)
203
203
  end
204
204
 
205
+ def _recompile_enabled?
206
+ ENV["DEPRECATION_COLLECTOR_RELOAD_WEB_TEMPLATES"]
207
+ end
208
+
205
209
  def _recompile_template(template, template_filename, template_method_name)
206
210
  original_template_name = File.join(VIEW_PATH, template.to_s)
207
211
  puts "Recompiling #{original_template_name}"
@@ -0,0 +1,12 @@
1
+ header
2
+ h1 Import dump
3
+
4
+ main
5
+ form method="post" action=import_deprecations_path enctype="multipart/form-data"
6
+ .mb-3
7
+ label.form-label> for="file" Choose a JSON file to upload:
8
+ input.form-comtrol type="file" name="file" id="file"
9
+ .mb-3
10
+ button.btn.btn-primary> type="submit" Upload
11
+ a.btn.btn-secondary> href=dump_deprecations_path Dump
12
+ a.btn.btn-secondary> href=deprecations_path Back
@@ -1,4 +1,4 @@
1
- _buf = ''; _buf << ("<header><h1>Import dump</h1></header><main><form".freeze);
1
+ _buf = ''.dup; _buf << ("<header><h1>Import dump</h1></header><main><form".freeze);
2
2
  ;
3
3
  ;
4
4
  ;
@@ -0,0 +1,121 @@
1
+ header.mb-3
2
+ h1 Deprecations
3
+
4
+ a.btn.btn-primary>(data-method="post" href=deprecation_path(:trigger) rel="nofollow") Trigger a couple
5
+ a.btn.btn-danger>(data-method="delete" data-confirm="Sure?" href=deprecation_path(:all) rel="nofollow")
6
+ i.bi.bi-trash
7
+ ' Delete all
8
+
9
+ - if DeprecationCollector.instance.storage.support_disabling?
10
+ - if DeprecationCollector.instance.storage.enabled?
11
+ a.btn.btn-danger>(
12
+ data-method="delete" href=disable_deprecations_path rel="nofollow"
13
+ data-confirm="Sure? Will need to restart workers after enabling"
14
+ ) Disable
15
+ - else
16
+ a.btn.btn-secondary>(
17
+ data-method="post" href=enable_deprecations_path rel="nofollow"
18
+ ) Turn on (after workers restart)
19
+
20
+ main
21
+ table.table.table-striped
22
+ tr
23
+ th Count
24
+ th Message
25
+ th Location
26
+ th Ruby/Rails
27
+
28
+ - total = 0
29
+ - by_realm = Hash.new(0)
30
+ - deprecations.each do |deprecation|
31
+ - total += 1
32
+ - by_realm[deprecation[:realm]] += 1
33
+ tr data-digest=deprecation[:digest]
34
+ td
35
+ a href=deprecation_path(deprecation[:digest]) = deprecation[:count]
36
+ br
37
+ - deprecation_tags(deprecation).each_pair do |tag, cls|
38
+ .badge> class=cls = tag
39
+
40
+ td
41
+ ruby:
42
+ msg = deprecation[:message].to_s
43
+ delete_prefixes = Gem.path + [defined?(Rails) && Rails.root.to_s].compact
44
+ delete_prefixes.each { |path| msg = msg.gsub(path, '') }
45
+ msg.delete_prefix! deprecation[:gem_traceline].gsub(/:in .+/, ':') if deprecation[:gem_traceline]
46
+ msg.delete_prefix! deprecation[:app_traceline].gsub(/:in .+/, ':') if deprecation[:app_traceline]
47
+ msg.strip!
48
+ msg.delete_prefix!("DEPRECATION WARNING: ")
49
+ msg.delete_prefix!("warning: ")
50
+
51
+ - if msg.lines.size > 2
52
+ pre.pre-scrollable.p-1(style="overflow: auto; max-width: 700px; max-height: 200px; font-size: 11px")
53
+ code = msg
54
+ - else
55
+ .msg = msg
56
+ - if deprecation.dig(:notes, :comment)
57
+ = deprecation.dig(:notes, :comment)
58
+
59
+ - if deprecation.dig(:context, :action)
60
+ i.small.controller = deprecation.dig(:context, :action)
61
+ - elsif deprecation.dig(:context, :params, :controller)
62
+ i.small.controller = deprecation.dig(:context, :params).slice(:controller, :action).values.join('#')
63
+
64
+ td.small
65
+ - if deprecation[:gem_traceline]
66
+ .gem_location
67
+ - location, function = deprecation[:gem_traceline].split(':in `', 2)
68
+ - full_gemname = location.delete_prefix('/gems/').gsub(%r{/.*}, '')
69
+ - location_in_gem = location.delete_prefix("/gems/#{full_gemname}/")
70
+ i>= full_gemname
71
+ code.code_location> data-copy-value=location_in_gem = location_in_gem.delete_prefix('lib/')
72
+ i= function.delete_suffix("'")
73
+ - if deprecation[:app_traceline]
74
+ .app_location
75
+ - location, function = deprecation[:app_traceline].split(':in `', 2)
76
+ code.code_location>= location
77
+ i= function.delete_suffix("'")
78
+ td
79
+ .small.ruby = deprecation[:ruby_version]
80
+ .small.rails = deprecation[:rails_version]
81
+
82
+ a href=deprecation_path(deprecation[:digest]) data-method="delete" data-confirm="Delete?" rel="nofollow" title="Delete"
83
+ i.bi.bi-trash
84
+ - if total.zero?
85
+ tr
86
+ td colspan=4
87
+ p Looks like there're no deprecations (or workers have not yet wrote to redis)
88
+ p
89
+ ' You can try
90
+ a href=deprecation_path(:trigger) data-method="post" rel="nofollow" trigger a couple
91
+ - if import_enabled?
92
+ |> , or
93
+ a> href=import_deprecations_path import
94
+
95
+
96
+ footer
97
+ - if total > 3
98
+ => total
99
+ ' deprecations
100
+ - by_realm.each_pair do |realm, count|
101
+ a.btn.btn-sm.btn-outline-secondary> href="?realm=#{realm}"
102
+ => realm
103
+ .badge> class=(count == 0 ? 'bg-success' : 'bg-secondary') = count
104
+ - if params[:realm] && params[:realm] != ''
105
+ a.btn.btn-sm.btn-outline-primary> href="?realm="
106
+ ' Other realms
107
+
108
+ css:
109
+ .code_location {
110
+ cursor: pointer;
111
+ }
112
+
113
+ javascript:
114
+ document.querySelectorAll('.code_location').forEach(function(elem){
115
+ elem.addEventListener('click', function () {
116
+ let textToCopy = elem.getAttribute('data-copy-value');
117
+ if(!textToCopy) textToCopy = elem.innerText;
118
+ console.log("Copying", textToCopy)
119
+ navigator.clipboard.writeText(textToCopy);
120
+ }, false);
121
+ });
@@ -1,4 +1,4 @@
1
- _buf = ''; _buf << ("<header class=\"mb-3\"><h1>Deprecations</h1><a class=\"btn btn-primary\" data-method=\"post\"".freeze);
1
+ _buf = ''.dup; _buf << ("<header class=\"mb-3\"><h1>Deprecations</h1><a class=\"btn btn-primary\" data-method=\"post\"".freeze);
2
2
  ;
3
3
  ;
4
4
  ; _slim_codeattributes1 = deprecation_path(:trigger); if _slim_codeattributes1; if _slim_codeattributes1 == true; _buf << (" href=\"\"".freeze); else; _buf << (" href=\"".freeze); _buf << ((::Temple::Utils.escape_html((_slim_codeattributes1))).to_s); _buf << ("\"".freeze); end; end; _buf << (" rel=\"nofollow\">Trigger a couple</a> <a class=\"btn btn-danger\" data-confirm=\"Sure?\" data-method=\"delete\"".freeze);
@@ -27,7 +27,7 @@ _buf = ''; _buf << ("<header class=\"mb-3\"><h1>Deprecations</h1><a class=\"btn
27
27
  ;
28
28
  ; total = 0;
29
29
  ; by_realm = Hash.new(0);
30
- ; @deprecations.each do |deprecation|;
30
+ ; deprecations.each do |deprecation|;
31
31
  ; total += 1;
32
32
  ; by_realm[deprecation[:realm]] += 1;
33
33
  ; _buf << ("<tr".freeze); _slim_codeattributes5 = deprecation[:digest]; if _slim_codeattributes5; if _slim_codeattributes5 == true; _buf << (" data-digest=\"\"".freeze); else; _buf << (" data-digest=\"".freeze); _buf << ((::Temple::Utils.escape_html((_slim_codeattributes5))).to_s); _buf << ("\"".freeze); end; end; _buf << ("><td><a".freeze);
@@ -35,13 +35,13 @@ _buf = ''; _buf << ("<header class=\"mb-3\"><h1>Deprecations</h1><a class=\"btn
35
35
  ; _slim_codeattributes6 = deprecation_path(deprecation[:digest]); if _slim_codeattributes6; if _slim_codeattributes6 == true; _buf << (" href=\"\"".freeze); else; _buf << (" href=\"".freeze); _buf << ((::Temple::Utils.escape_html((_slim_codeattributes6))).to_s); _buf << ("\"".freeze); end; end; _buf << (">".freeze); _buf << ((::Temple::Utils.escape_html((deprecation[:count]))).to_s);
36
36
  ; _buf << ("</a><br />".freeze);
37
37
  ; deprecation_tags(deprecation).each_pair do |tag, cls|;
38
- ; _buf << ("<div".freeze); _temple_html_attributeremover1 = ''; _temple_html_attributemerger1 = []; _temple_html_attributemerger1[0] = "badge"; _temple_html_attributemerger1[1] = ''; _slim_codeattributes7 = cls; if Array === _slim_codeattributes7; _slim_codeattributes7 = _slim_codeattributes7.flatten; _slim_codeattributes7.map!(&:to_s); _slim_codeattributes7.reject!(&:empty?); _temple_html_attributemerger1[1] << ((::Temple::Utils.escape_html((_slim_codeattributes7.join(" ")))).to_s); else; _temple_html_attributemerger1[1] << ((::Temple::Utils.escape_html((_slim_codeattributes7))).to_s); end; _temple_html_attributemerger1[1]; _temple_html_attributeremover1 << ((_temple_html_attributemerger1.reject(&:empty?).join(" ")).to_s); _temple_html_attributeremover1; if !_temple_html_attributeremover1.empty?; _buf << (" class=\"".freeze); _buf << ((_temple_html_attributeremover1).to_s); _buf << ("\"".freeze); end; _buf << (">".freeze); _buf << ((::Temple::Utils.escape_html((tag))).to_s);
38
+ ; _buf << ("<div".freeze); _temple_html_attributeremover1 = ''.dup; _temple_html_attributemerger1 = []; _temple_html_attributemerger1[0] = "badge"; _temple_html_attributemerger1[1] = ''.dup; _slim_codeattributes7 = cls; if Array === _slim_codeattributes7; _slim_codeattributes7 = _slim_codeattributes7.flatten; _slim_codeattributes7.map!(&:to_s); _slim_codeattributes7.reject!(&:empty?); _temple_html_attributemerger1[1] << ((::Temple::Utils.escape_html((_slim_codeattributes7.join(" ")))).to_s); else; _temple_html_attributemerger1[1] << ((::Temple::Utils.escape_html((_slim_codeattributes7))).to_s); end; _temple_html_attributemerger1[1]; _temple_html_attributeremover1 << ((_temple_html_attributemerger1.reject(&:empty?).join(" ")).to_s); _temple_html_attributeremover1; if !_temple_html_attributeremover1.empty?; _buf << (" class=\"".freeze); _buf << ((_temple_html_attributeremover1).to_s); _buf << ("\"".freeze); end; _buf << (">".freeze); _buf << ((::Temple::Utils.escape_html((tag))).to_s);
39
39
  ;
40
40
  ; _buf << ("</div> ".freeze); end; _buf << ("</td><td>".freeze);
41
41
  ;
42
- ; msg = deprecation[:message]
42
+ ; msg = deprecation[:message].to_s
43
43
  delete_prefixes = Gem.path + [defined?(Rails) && Rails.root.to_s].compact
44
- delete_prefixes.each { |path| msg.gsub!(path, '') }
44
+ delete_prefixes.each { |path| msg = msg.gsub(path, '') }
45
45
  msg.delete_prefix! deprecation[:gem_traceline].gsub(/:in .+/, ':') if deprecation[:gem_traceline]
46
46
  msg.delete_prefix! deprecation[:app_traceline].gsub(/:in .+/, ':') if deprecation[:app_traceline]
47
47
  msg.strip!
@@ -100,7 +100,7 @@ msg.delete_prefix!("warning: ")
100
100
  ; end; by_realm.each_pair do |realm, count|;
101
101
  ; _buf << ("<a class=\"btn btn-sm btn-outline-secondary\" href=\"?realm=".freeze); _buf << ((::Temple::Utils.escape_html((realm))).to_s); _buf << ("\">".freeze);
102
102
  ; _buf << ((::Temple::Utils.escape_html((realm))).to_s);
103
- ; _buf << (" <div".freeze); _temple_html_attributeremover2 = ''; _temple_html_attributemerger2 = []; _temple_html_attributemerger2[0] = "badge"; _temple_html_attributemerger2[1] = ''; _slim_codeattributes13 = (count == 0 ? 'bg-success' : 'bg-secondary'); if Array === _slim_codeattributes13; _slim_codeattributes13 = _slim_codeattributes13.flatten; _slim_codeattributes13.map!(&:to_s); _slim_codeattributes13.reject!(&:empty?); _temple_html_attributemerger2[1] << ((::Temple::Utils.escape_html((_slim_codeattributes13.join(" ")))).to_s); else; _temple_html_attributemerger2[1] << ((::Temple::Utils.escape_html((_slim_codeattributes13))).to_s); end; _temple_html_attributemerger2[1]; _temple_html_attributeremover2 << ((_temple_html_attributemerger2.reject(&:empty?).join(" ")).to_s); _temple_html_attributeremover2; if !_temple_html_attributeremover2.empty?; _buf << (" class=\"".freeze); _buf << ((_temple_html_attributeremover2).to_s); _buf << ("\"".freeze); end; _buf << (">".freeze); _buf << ((::Temple::Utils.escape_html((count))).to_s);
103
+ ; _buf << (" <div".freeze); _temple_html_attributeremover2 = ''.dup; _temple_html_attributemerger2 = []; _temple_html_attributemerger2[0] = "badge"; _temple_html_attributemerger2[1] = ''.dup; _slim_codeattributes13 = (count == 0 ? 'bg-success' : 'bg-secondary'); if Array === _slim_codeattributes13; _slim_codeattributes13 = _slim_codeattributes13.flatten; _slim_codeattributes13.map!(&:to_s); _slim_codeattributes13.reject!(&:empty?); _temple_html_attributemerger2[1] << ((::Temple::Utils.escape_html((_slim_codeattributes13.join(" ")))).to_s); else; _temple_html_attributemerger2[1] << ((::Temple::Utils.escape_html((_slim_codeattributes13))).to_s); end; _temple_html_attributemerger2[1]; _temple_html_attributeremover2 << ((_temple_html_attributemerger2.reject(&:empty?).join(" ")).to_s); _temple_html_attributeremover2; if !_temple_html_attributeremover2.empty?; _buf << (" class=\"".freeze); _buf << ((_temple_html_attributeremover2).to_s); _buf << ("\"".freeze); end; _buf << (">".freeze); _buf << ((::Temple::Utils.escape_html((count))).to_s);
104
104
  ; _buf << ("</div> </a> ".freeze); end; if params[:realm] && params[:realm] != '';
105
105
  ; _buf << ("<a class=\"btn btn-sm btn-outline-primary\" href=\"?realm=\">Other realms </a> ".freeze);
106
106
  ;