deprecation_collector 0.5.2 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
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
  ;