uncruft 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.md +53 -0
- data/Rakefile +24 -0
- data/lib/uncruft.rb +19 -0
- data/lib/uncruft/deprecation_handler.rb +122 -0
- data/lib/uncruft/railtie.rb +14 -0
- data/lib/uncruft/version.rb +3 -0
- data/lib/uncruft/warning.rb +32 -0
- data/spec/dummy/config/application.rb +8 -0
- data/spec/dummy/config/deprecations.ignore +7 -0
- data/spec/dummy/log/test.log +0 -0
- data/spec/examples.txt +24 -0
- data/spec/spec_helper.rb +13 -0
- data/spec/support/rails_root.rb +7 -0
- data/spec/uncruft/deprecation_handler_spec.rb +172 -0
- data/spec/uncruft/railtie_spec.rb +33 -0
- data/spec/uncruft/warning_spec.rb +41 -0
- data/spec/uncruft_spec.rb +46 -0
- metadata +158 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: fdb195d4b08809aa2c07c8496fcc908f11fcc990
|
4
|
+
data.tar.gz: 5790bc811ae97d8d3de5a851c26cd707b452b530
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 766cefcb5c8b903953292269ad4ae8e451c4f1dd5f6f2b01d2c3f3283aefead950614b7354f9f28022ede6749aacfc042751c6cd9e9145b79b92bf5bb04d3df5
|
7
|
+
data.tar.gz: ace1be673782194643ffb5fe4b931fb7e7f947083084cb6c1c1af62deec03ef76ba44fb36c41384de516f97aaf2386b4957431f57d0c0f803bad8598bec4c243
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2018 Betterment
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
7
|
+
the Software without restriction, including without limitation the rights to
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
9
|
+
of the Software, and to permit persons to whom the Software is furnished to do
|
10
|
+
so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
Uncruft
|
2
|
+
========
|
3
|
+
|
4
|
+
A library to assist with clearing out Rails deprecation warnings and upgrading Rails versions.
|
5
|
+
|
6
|
+
## Getting Started
|
7
|
+
|
8
|
+
Uncruft is designed to work with Rails 4.2 and higher.
|
9
|
+
|
10
|
+
### Installation
|
11
|
+
|
12
|
+
You can add Uncruft to your Gemfile with:
|
13
|
+
|
14
|
+
```
|
15
|
+
gem 'uncruft'
|
16
|
+
```
|
17
|
+
|
18
|
+
Then run `bundle install`.
|
19
|
+
|
20
|
+
### Deprecation Warnings
|
21
|
+
|
22
|
+
By default, deprecation warnings will cause your application to raise exceptions in `test` and `development` modes.
|
23
|
+
|
24
|
+
The exception message will include the original deprecation warning, plus a link to [our troubleshooting guide](https://github.com/Betterment/uncruft/blob/master/GUIDE.md), to assist with resolving deprecations as they are encountered.
|
25
|
+
|
26
|
+
## Whitelisting Deprecations
|
27
|
+
|
28
|
+
When testing on a new Rails version for the first time, you will undoubtedly encounter many new warnings. As such, you can quickly whitelist all existing deprecation warnings encountered during your test suite like so:
|
29
|
+
|
30
|
+
```bash
|
31
|
+
WHITELIST_DEPRECATIONS=1 rake
|
32
|
+
```
|
33
|
+
|
34
|
+
You can also incrementally add new warnings to the whitelist as you encounter them:
|
35
|
+
|
36
|
+
```bash
|
37
|
+
WHITELIST_DEPRECATIONS=1 rspec path/to/my/failing/spec.rb
|
38
|
+
```
|
39
|
+
|
40
|
+
This will generate (or add to) a whitelist of warnings at `config/deprecations.ignore`. Any warning in that file will be ignored when next encountered.
|
41
|
+
|
42
|
+
## How to Contribute
|
43
|
+
|
44
|
+
We would love for you to contribute! Anything that benefits the majority of users—from a documentation fix to an entirely new feature—is encouraged.
|
45
|
+
|
46
|
+
Before diving in, [check our issue tracker](//github.com/Betterment/uncruft/issues) and consider creating a new issue to get early feedback on your proposed change.
|
47
|
+
|
48
|
+
### Suggested Workflow
|
49
|
+
|
50
|
+
* Fork the project and create a new branch for your contribution.
|
51
|
+
* Write your contribution (and any applicable test coverage).
|
52
|
+
* Make sure all tests pass (`bundle exec rake`).
|
53
|
+
* Submit a pull request.
|
data/Rakefile
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
|
7
|
+
Bundler::GemHelper.install_tasks
|
8
|
+
|
9
|
+
task(:default).clear
|
10
|
+
|
11
|
+
require 'rubocop/rake_task'
|
12
|
+
RuboCop::RakeTask.new
|
13
|
+
|
14
|
+
require 'rspec/core'
|
15
|
+
require 'rspec/core/rake_task'
|
16
|
+
RSpec::Core::RakeTask.new(:spec)
|
17
|
+
|
18
|
+
if ENV['APPRAISAL_INITIALIZED'] || ENV['TRAVIS']
|
19
|
+
task default: %i(rubocop spec)
|
20
|
+
else
|
21
|
+
require 'appraisal'
|
22
|
+
Appraisal::Task.new
|
23
|
+
task default: :appraisal
|
24
|
+
end
|
data/lib/uncruft.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'uncruft/version'
|
2
|
+
require 'uncruft/railtie'
|
3
|
+
require 'uncruft/deprecation_handler'
|
4
|
+
require 'uncruft/warning'
|
5
|
+
|
6
|
+
module Uncruft
|
7
|
+
class << self
|
8
|
+
# http://api.rubyonrails.org/classes/ActiveModel/Type/Boolean.html
|
9
|
+
FALSE_VALUES = [false, 0, "0", "f", "F", "false", "FALSE", "off", "OFF"].to_set
|
10
|
+
|
11
|
+
def whitelist_deprecations?
|
12
|
+
ENV['WHITELIST_DEPRECATIONS'].presence && !FALSE_VALUES.include?(ENV['WHITELIST_DEPRECATIONS'])
|
13
|
+
end
|
14
|
+
|
15
|
+
def ignorefile_path
|
16
|
+
ENV['UNCRUFT_IGNOREFILE_PATH'] || Rails.root.join('config', 'deprecations.ignore')
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
module Uncruft
|
4
|
+
class DeprecationHandler
|
5
|
+
def call(message, _callstack)
|
6
|
+
line_number = line_number(message)
|
7
|
+
message = normalize_message(message)
|
8
|
+
handle_unknown_deprecation!(message, line_number) unless known_deprecations.include?(message)
|
9
|
+
end
|
10
|
+
|
11
|
+
def arity
|
12
|
+
2
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def handle_unknown_deprecation!(message, line_number)
|
18
|
+
if Uncruft.whitelist_deprecations?
|
19
|
+
known_deprecations << message
|
20
|
+
write_deprecations_file!
|
21
|
+
else
|
22
|
+
raise error_message(message, line_number)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def write_deprecations_file!
|
27
|
+
file = File.open(Uncruft.ignorefile_path, 'w')
|
28
|
+
file.puts(file_content(known_deprecations))
|
29
|
+
file.close
|
30
|
+
end
|
31
|
+
|
32
|
+
def line_number(message)
|
33
|
+
message.match(/called from( .+ at)? .+:(\d+)/)&.[](2)
|
34
|
+
end
|
35
|
+
|
36
|
+
# Rails deprecation message formats found here:
|
37
|
+
# https://github.com/rails/rails/blob/5-0-stable/activesupport/lib/active_support/deprecation/reporting.rb#L75
|
38
|
+
def normalize_message(message)
|
39
|
+
remove_line_number(normalize_caller(normalize_callstack_path(message)))
|
40
|
+
end
|
41
|
+
|
42
|
+
def normalize_callstack_path(message)
|
43
|
+
if (gem_home = gem_home(message)).present?
|
44
|
+
message.gsub(gem_home, '$GEM_PATH')
|
45
|
+
elsif (absolute_path = absolute_path(message)).present?
|
46
|
+
message.gsub(absolute_path, relative_path(absolute_path))
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def normalize_caller(message)
|
51
|
+
normalize_require_callers(remove_view_callers(message))
|
52
|
+
end
|
53
|
+
|
54
|
+
def normalize_require_callers(message)
|
55
|
+
message.gsub(/ <(top \(required\)|main)> at /, ' <global scope> at ')
|
56
|
+
end
|
57
|
+
|
58
|
+
def remove_view_callers(message)
|
59
|
+
message.gsub(/ _\w+__+\d+_\d+ at /, ' ')
|
60
|
+
end
|
61
|
+
|
62
|
+
def remove_line_number(message)
|
63
|
+
message.sub(/(called from( .+ at)? .+):\d+/, '\1')
|
64
|
+
end
|
65
|
+
|
66
|
+
def gem_home(message)
|
67
|
+
message.match(%r{called from( .+ at)? (#{ENV['GEM_HOME']}/(.+/)*gems)})&.[](2)
|
68
|
+
end
|
69
|
+
|
70
|
+
def absolute_path(message)
|
71
|
+
message.match(/called from( .+ at)? (.+):\d/)&.[](2)
|
72
|
+
end
|
73
|
+
|
74
|
+
def relative_path(absolute_path)
|
75
|
+
Pathname.new(absolute_path)
|
76
|
+
.relative_path_from(Rails.root).to_s
|
77
|
+
.gsub(%r{\A(../)*vendor/cache}, '$GEM_PATH')
|
78
|
+
rescue ArgumentError # When `relative_path_from` cannot find a relative path.
|
79
|
+
absolute_path
|
80
|
+
end
|
81
|
+
|
82
|
+
def error_message(message, line_number)
|
83
|
+
<<~ERROR.strip
|
84
|
+
#{message}:#{line_number}
|
85
|
+
|
86
|
+
To resolve this error, adjust your code according to the instructions above.
|
87
|
+
If you did not introduce this error or are unsure why you are seeing it,
|
88
|
+
you will find additional guidance at the URL below:
|
89
|
+
https://github.com/Betterment/uncruft/blob/master/GUIDE.md
|
90
|
+
ERROR
|
91
|
+
end
|
92
|
+
|
93
|
+
def known_deprecations_file_exists?
|
94
|
+
File.file?(Uncruft.ignorefile_path)
|
95
|
+
end
|
96
|
+
|
97
|
+
def known_deprecations
|
98
|
+
@known_deprecations ||= begin
|
99
|
+
if known_deprecations_file_exists?
|
100
|
+
file = File.read(Uncruft.ignorefile_path)
|
101
|
+
JSON.parse(file)['ignored_warnings'].to_set
|
102
|
+
else
|
103
|
+
Set.new
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def file_content(deprecations)
|
109
|
+
JSON.pretty_generate ignored_warnings: deprecations.sort,
|
110
|
+
updated: now,
|
111
|
+
rails_version: Rails::VERSION::STRING
|
112
|
+
end
|
113
|
+
|
114
|
+
def now
|
115
|
+
if defined?(Timecop)
|
116
|
+
Timecop.return { Time.zone.now }
|
117
|
+
else
|
118
|
+
Time.zone.now
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'rails'
|
2
|
+
|
3
|
+
module Uncruft
|
4
|
+
class Railtie < ::Rails::Railtie
|
5
|
+
if Rails.env.test? || Rails.env.development?
|
6
|
+
initializer 'uncruft.deprecation_handler', before: 'active_support.deprecation_behavior' do
|
7
|
+
strategies = [config.active_support.deprecation].flatten(1).compact
|
8
|
+
strategies.reject! { |s| s == :stderr }
|
9
|
+
strategies.unshift(DeprecationHandler.new)
|
10
|
+
config.active_support.deprecation = strategies
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Uncruft
|
2
|
+
module Warning
|
3
|
+
DEPRECATION_PATTERN = /(deprecation|deprecated)/i
|
4
|
+
|
5
|
+
def warn(str)
|
6
|
+
if str =~ DEPRECATION_PATTERN # rubocop:disable Performance/RegexpMatch
|
7
|
+
message = strip_caller_info(str, caller_locations(1..1).first).strip
|
8
|
+
ActiveSupport::Deprecation.warn(message)
|
9
|
+
else
|
10
|
+
super
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def strip_caller_info(str, cloc)
|
17
|
+
str.sub(cloc.to_s, '') # try full caller information first
|
18
|
+
.gsub(/#{cloc.path}(:#{cloc.lineno})?:?\s*/, '') # try path with optional line
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
if Rails.env.development? || Rails.env.test?
|
24
|
+
if defined?(Warning)
|
25
|
+
Warning.prepend(Uncruft::Warning)
|
26
|
+
Warning.singleton_class.prepend(Uncruft::Warning)
|
27
|
+
end
|
28
|
+
Kernel.prepend(Uncruft::Warning)
|
29
|
+
Kernel.singleton_class.prepend(Uncruft::Warning)
|
30
|
+
Object.prepend(Uncruft::Warning)
|
31
|
+
Object.singleton_class.prepend(Uncruft::Warning)
|
32
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../../Gemfile', __dir__)
|
2
|
+
require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
|
3
|
+
$LOAD_PATH.unshift File.expand_path('../../../lib', __dir__)
|
4
|
+
|
5
|
+
module Dummy
|
6
|
+
class Application < Rails::Application
|
7
|
+
end
|
8
|
+
end
|
File without changes
|
data/spec/examples.txt
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
example_id | status | run_time |
|
2
|
+
------------------------------------------------------- | ------ | --------------- |
|
3
|
+
./spec/uncruft/deprecation_handler_spec.rb[1:1:1] | passed | 0.00321 seconds |
|
4
|
+
./spec/uncruft/deprecation_handler_spec.rb[1:1:2:1] | passed | 0.01779 seconds |
|
5
|
+
./spec/uncruft/deprecation_handler_spec.rb[1:1:2:2:1] | passed | 0.00596 seconds |
|
6
|
+
./spec/uncruft/deprecation_handler_spec.rb[1:1:3:1] | passed | 0.00079 seconds |
|
7
|
+
./spec/uncruft/deprecation_handler_spec.rb[1:1:4:1] | passed | 0.00071 seconds |
|
8
|
+
./spec/uncruft/deprecation_handler_spec.rb[1:1:5:1] | passed | 0.00247 seconds |
|
9
|
+
./spec/uncruft/deprecation_handler_spec.rb[1:1:6:1] | passed | 0.0026 seconds |
|
10
|
+
./spec/uncruft/deprecation_handler_spec.rb[1:1:6:2:1] | passed | 0.0029 seconds |
|
11
|
+
./spec/uncruft/deprecation_handler_spec.rb[1:1:6:3:1] | passed | 0.00142 seconds |
|
12
|
+
./spec/uncruft/deprecation_handler_spec.rb[1:1:6:3:2:1] | passed | 0.00168 seconds |
|
13
|
+
./spec/uncruft/deprecation_handler_spec.rb[1:1:7:1] | passed | 0.00052 seconds |
|
14
|
+
./spec/uncruft/deprecation_handler_spec.rb[1:1:8:1] | passed | 0.00211 seconds |
|
15
|
+
./spec/uncruft/deprecation_handler_spec.rb[1:1:8:2:1] | passed | 0.00335 seconds |
|
16
|
+
./spec/uncruft/railtie_spec.rb[1:1] | passed | 0.06556 seconds |
|
17
|
+
./spec/uncruft/railtie_spec.rb[1:2:1] | passed | 0.00156 seconds |
|
18
|
+
./spec/uncruft/railtie_spec.rb[1:3:1] | passed | 0.00133 seconds |
|
19
|
+
./spec/uncruft/warning_spec.rb[1:1] | passed | 0.00076 seconds |
|
20
|
+
./spec/uncruft/warning_spec.rb[1:2:1] | passed | 0.00158 seconds |
|
21
|
+
./spec/uncruft/warning_spec.rb[1:2:2:1] | passed | 0.00142 seconds |
|
22
|
+
./spec/uncruft_spec.rb[1:1:1] | passed | 0.00533 seconds |
|
23
|
+
./spec/uncruft_spec.rb[1:2:1] | passed | 0.00091 seconds |
|
24
|
+
./spec/uncruft_spec.rb[1:2:2:1] | passed | 0.00151 seconds |
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
Bundler.require :default, :development
|
3
|
+
|
4
|
+
ENV["RAILS_ENV"] ||= 'test'
|
5
|
+
require File.expand_path('dummy/config/application', __dir__)
|
6
|
+
require 'support/rails_root'
|
7
|
+
|
8
|
+
Time.zone = ActiveSupport::TimeZone.all.first
|
9
|
+
|
10
|
+
RSpec.configure do |config|
|
11
|
+
config.run_all_when_everything_filtered = true
|
12
|
+
config.example_status_persistence_file_path = 'spec/examples.txt'
|
13
|
+
end
|
@@ -0,0 +1,172 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe Uncruft::DeprecationHandler do
|
4
|
+
let(:ignorefile_path) { Rails.root.join('config', 'deprecations.ignore') }
|
5
|
+
|
6
|
+
before do
|
7
|
+
File.delete(ignorefile_path) if File.exist?(ignorefile_path)
|
8
|
+
end
|
9
|
+
|
10
|
+
subject { described_class.new }
|
11
|
+
|
12
|
+
describe '#call' do
|
13
|
+
let(:absolute_path) { Rails.root.join('chicken', 'nuggets.rb') }
|
14
|
+
let(:line_number) { 123 }
|
15
|
+
let(:caller_label) { '<something>' }
|
16
|
+
let(:message) { "Warning: BAD called from #{caller_label} at #{absolute_path}:#{line_number}" }
|
17
|
+
let(:expected_whitelist_entry) { 'Warning: BAD called from <something> at chicken/nuggets.rb' }
|
18
|
+
let(:expected_error) { "#{expected_whitelist_entry}:123" }
|
19
|
+
let(:expected_error_message) do
|
20
|
+
<<~ERROR.strip
|
21
|
+
#{expected_error}
|
22
|
+
|
23
|
+
To resolve this error, adjust your code according to the instructions above.
|
24
|
+
If you did not introduce this error or are unsure why you are seeing it,
|
25
|
+
you will find additional guidance at the URL below:
|
26
|
+
https://github.com/Betterment/uncruft/blob/master/GUIDE.md
|
27
|
+
ERROR
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'sanitizes the message and raises an error' do
|
31
|
+
expect { subject.call(message, '') }.to raise_error(RuntimeError, expected_error_message)
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'when whitelisting new deprecations' do
|
35
|
+
before do
|
36
|
+
allow(Uncruft).to receive(:whitelist_deprecations?).and_return(true)
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'sanitizes the message and writes it to the file' do
|
40
|
+
expect { subject.call(message, '') }.to change { File.exist?(ignorefile_path) }.from(false).to(true)
|
41
|
+
expect(File.read(ignorefile_path)).to include(expected_whitelist_entry)
|
42
|
+
end
|
43
|
+
|
44
|
+
context 'when timecop is enabled' do
|
45
|
+
let(:test_started) { Time.zone.now }
|
46
|
+
|
47
|
+
it 'ignores time travel and writes the current time' do
|
48
|
+
Timecop.travel(test_started - 100.years) do
|
49
|
+
subject.call(message, '')
|
50
|
+
|
51
|
+
file_updated = Time.zone.parse(JSON.parse(File.read(ignorefile_path))['updated'])
|
52
|
+
expect(file_updated).to be_within(1.second).of(test_started)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
context 'when caller is an erb file' do
|
59
|
+
let(:caller_label) { '_app_views_bananas_show__1234_567890' }
|
60
|
+
let(:expected_whitelist_entry) { 'Warning: BAD called from chicken/nuggets.rb' }
|
61
|
+
|
62
|
+
it 'sanitizes the message and raises an error' do
|
63
|
+
expect { subject.call(message, '') }.to raise_error(RuntimeError, expected_error_message)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context 'when caller is "top (required)"' do
|
68
|
+
let(:caller_label) { '<top (required)>' }
|
69
|
+
let(:expected_whitelist_entry) { 'Warning: BAD called from <global scope> at chicken/nuggets.rb' }
|
70
|
+
|
71
|
+
it 'sanitizes the caller and raises an error' do
|
72
|
+
expect { subject.call(message, '') }.to raise_error(RuntimeError, expected_error_message)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
context 'when caller is "main"' do
|
77
|
+
let(:caller_label) { '<main>' }
|
78
|
+
let(:expected_whitelist_entry) { 'Warning: BAD called from <global scope> at chicken/nuggets.rb' }
|
79
|
+
|
80
|
+
it 'sanitizes the caller and raises an error' do
|
81
|
+
expect { subject.call(message, '') }.to raise_error(RuntimeError, expected_error_message)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
context 'when message includes custom gem path' do
|
86
|
+
let(:absolute_path) { Pathname.new('/banana/banana/banana/gems/chicken/nuggets.rb') }
|
87
|
+
let(:expected_whitelist_entry) { "Warning: BAD called from <something> at $GEM_PATH/chicken/nuggets.rb" }
|
88
|
+
|
89
|
+
before do
|
90
|
+
allow(ENV).to receive(:[]).and_call_original
|
91
|
+
allow(ENV).to receive(:[]).with('GEM_HOME').and_return('/banana/banana/banana')
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'sanitizes the message and raises an error' do
|
95
|
+
expect { subject.call(message, '') }.to raise_error(RuntimeError, expected_error_message)
|
96
|
+
end
|
97
|
+
|
98
|
+
context 'when gem home is nested' do
|
99
|
+
let(:absolute_path) { Pathname.new('/banana/banana/banana/arbitrary/gem/path/gems/chicken/nuggets.rb') }
|
100
|
+
|
101
|
+
it 'sanitizes the message and raises an error' do
|
102
|
+
expect { subject.call(message, '') }.to raise_error(RuntimeError, expected_error_message)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
context 'when gem is vendored' do
|
107
|
+
let(:absolute_path) { Rails.root.join('vendor', 'cache', 'chicken', 'nuggets.rb') }
|
108
|
+
|
109
|
+
it 'sanitizes the message and raises an error' do
|
110
|
+
expect { subject.call(message, '') }.to raise_error(RuntimeError, expected_error_message)
|
111
|
+
end
|
112
|
+
|
113
|
+
context 'when gem is vendored elsewhere' do
|
114
|
+
let(:absolute_path) { Rails.root.join('..', '..', 'vendor', 'cache', 'chicken', 'nuggets.rb') }
|
115
|
+
|
116
|
+
it 'sanitizes the message and raises an error' do
|
117
|
+
expect { subject.call(message, '') }.to raise_error(RuntimeError, expected_error_message)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
context 'when caller is not a filepath' do
|
124
|
+
let(:absolute_path) { '(pry)' }
|
125
|
+
let(:expected_whitelist_entry) { 'Warning: BAD called from <something> at (pry)' }
|
126
|
+
|
127
|
+
it 'sanitizes the message and raises an error' do
|
128
|
+
expect { subject.call(message, '') }.to raise_error(RuntimeError, expected_error_message)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
context 'when whitelist exists' do
|
133
|
+
let(:message) { "Warning: BAD called from #{absolute_path}:#{line_number}" }
|
134
|
+
let(:file_content) do
|
135
|
+
<<~IGNOREFILE
|
136
|
+
{
|
137
|
+
"ignored_warnings": [
|
138
|
+
"Warning: BAD called from chicken/nuggets.rb"
|
139
|
+
],
|
140
|
+
"updated": "2018-06-05 15:20:12 -0400",
|
141
|
+
"rails_version": "5.1.6"
|
142
|
+
}
|
143
|
+
IGNOREFILE
|
144
|
+
end
|
145
|
+
|
146
|
+
before do
|
147
|
+
File.open(ignorefile_path, 'w') do |f|
|
148
|
+
f.write file_content
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
it 'does not raise an error and leaves the file intact' do
|
153
|
+
expect(File.read(ignorefile_path)).to eq(file_content)
|
154
|
+
expect { subject.call(message, '') }.not_to change { File.read(ignorefile_path) }
|
155
|
+
end
|
156
|
+
|
157
|
+
context 'when whitelisting new deprecations' do
|
158
|
+
let(:line_number) { '456' }
|
159
|
+
|
160
|
+
before do
|
161
|
+
allow(Uncruft).to receive(:whitelist_deprecations?).and_return(true)
|
162
|
+
end
|
163
|
+
|
164
|
+
it 'does not raise an error and leaves the file intact' do
|
165
|
+
expect(File.read(ignorefile_path)).to eq(file_content)
|
166
|
+
expect { subject.call(message, '') }.not_to raise_error
|
167
|
+
expect(File.read(ignorefile_path)).to include('Warning: BAD called from chicken/nuggets.rb')
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Uncruft::Railtie do
|
4
|
+
let(:app) { Rails.application }
|
5
|
+
let(:initializers) { app.initializers.tsort_each.select { |i| i.name.to_s.include?('deprecation') } }
|
6
|
+
|
7
|
+
it 'injects the default deprecation handler' do
|
8
|
+
expect { initializers.map { |i| i.run(app) } }.to change { Rails.application.config.active_support.deprecation }
|
9
|
+
.from(nil).to(a_collection_containing_exactly(an_instance_of(Uncruft::DeprecationHandler)))
|
10
|
+
end
|
11
|
+
|
12
|
+
context 'when the configured behavior is :stderr' do
|
13
|
+
before do
|
14
|
+
Rails.application.config.active_support.deprecation = :stderr
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'injects the default deprecation handler' do
|
18
|
+
expect { initializers.map { |i| i.run(app) } }.to change { Rails.application.config.active_support.deprecation }
|
19
|
+
.from(:stderr).to(a_collection_containing_exactly(an_instance_of(Uncruft::DeprecationHandler)))
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context 'when a custom deprecation behavior is already configured' do
|
24
|
+
before do
|
25
|
+
Rails.application.config.active_support.deprecation = :notify
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'injects the default deprecation handler' do
|
29
|
+
expect { initializers.map { |i| i.run(app) } }.to change { Rails.application.config.active_support.deprecation }
|
30
|
+
.from(:notify).to(a_collection_containing_exactly(:notify, an_instance_of(Uncruft::DeprecationHandler)))
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Uncruft::Warning do
|
4
|
+
before do
|
5
|
+
stub_const('Warning', Kernel) unless defined?(Warning)
|
6
|
+
end
|
7
|
+
|
8
|
+
it "doesn't block generic warnings" do
|
9
|
+
expect(ActiveSupport::Deprecation).not_to receive(:warn)
|
10
|
+
warn('oh no, you should worry')
|
11
|
+
Kernel.warn('oh no, you should worry')
|
12
|
+
Warning.warn('oh no, you should worry')
|
13
|
+
end
|
14
|
+
|
15
|
+
context 'when warning includes the word "deprecation" or "deprecated"' do
|
16
|
+
it 'treats it as a deprecation warning' do
|
17
|
+
expect(ActiveSupport::Deprecation).to receive(:warn).and_return('banana').exactly(6).times
|
18
|
+
expect(warn('[dEpReCaTiOn] oh no, you should worry')).to eq 'banana'
|
19
|
+
expect(Kernel.warn('[dEpReCaTiOn] oh no, you should worry')).to eq 'banana'
|
20
|
+
expect(Warning.warn('[dEpReCaTiOn] oh no, you should worry')).to eq 'banana'
|
21
|
+
expect(warn('oh no, this is DePrEcAtEd, so you should worry')).to eq 'banana'
|
22
|
+
expect(Kernel.warn('oh no, this is DePrEcAtEd, so you should worry')).to eq 'banana'
|
23
|
+
expect(Warning.warn('oh no, this is DePrEcAtEd, so you should worry')).to eq 'banana'
|
24
|
+
end
|
25
|
+
|
26
|
+
context 'and when warning includes caller info' do
|
27
|
+
it 'strips out the path so that ActiveSupport::Deprecation can append a new one' do
|
28
|
+
path = caller_locations(0..0).first.path
|
29
|
+
|
30
|
+
expect(ActiveSupport::Deprecation).to receive(:warn).with('foo is deprecated!').and_return('hurray')
|
31
|
+
expect(warn("#{path}: foo is deprecated!")).to eq('hurray')
|
32
|
+
|
33
|
+
expect(ActiveSupport::Deprecation).to receive(:warn).with('[DEPRECATION] bar is no more.').and_return('huzzah')
|
34
|
+
expect(Kernel.warn("[DEPRECATION] bar is no more. #{path}:#{caller_locations(0..0).first.lineno}")).to eq('huzzah')
|
35
|
+
|
36
|
+
expect(ActiveSupport::Deprecation).to receive(:warn).with('Deprecation detected: banana --').and_return('we do our best...')
|
37
|
+
expect(Warning.warn("Deprecation detected: banana -- #{caller(0..0).first}")).to eq('we do our best...')
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe Uncruft do
|
4
|
+
describe '.whitelist_deprecations?' do
|
5
|
+
it 'handles common truthy and falsy values' do
|
6
|
+
allow(ENV).to receive(:[]).with('WHITELIST_DEPRECATIONS').and_return('1')
|
7
|
+
expect(described_class.whitelist_deprecations?).to eq true
|
8
|
+
allow(ENV).to receive(:[]).with('WHITELIST_DEPRECATIONS').and_return('t')
|
9
|
+
expect(described_class.whitelist_deprecations?).to eq true
|
10
|
+
allow(ENV).to receive(:[]).with('WHITELIST_DEPRECATIONS').and_return('T')
|
11
|
+
expect(described_class.whitelist_deprecations?).to eq true
|
12
|
+
allow(ENV).to receive(:[]).with('WHITELIST_DEPRECATIONS').and_return('true')
|
13
|
+
expect(described_class.whitelist_deprecations?).to eq true
|
14
|
+
allow(ENV).to receive(:[]).with('WHITELIST_DEPRECATIONS').and_return('TRUE')
|
15
|
+
expect(described_class.whitelist_deprecations?).to eq true
|
16
|
+
allow(ENV).to receive(:[]).with('WHITELIST_DEPRECATIONS').and_return('0')
|
17
|
+
expect(described_class.whitelist_deprecations?).to eq false
|
18
|
+
allow(ENV).to receive(:[]).with('WHITELIST_DEPRECATIONS').and_return('f')
|
19
|
+
expect(described_class.whitelist_deprecations?).to eq false
|
20
|
+
allow(ENV).to receive(:[]).with('WHITELIST_DEPRECATIONS').and_return('F')
|
21
|
+
expect(described_class.whitelist_deprecations?).to eq false
|
22
|
+
allow(ENV).to receive(:[]).with('WHITELIST_DEPRECATIONS').and_return('false')
|
23
|
+
expect(described_class.whitelist_deprecations?).to eq false
|
24
|
+
allow(ENV).to receive(:[]).with('WHITELIST_DEPRECATIONS').and_return('FALSE')
|
25
|
+
expect(described_class.whitelist_deprecations?).to eq false
|
26
|
+
allow(ENV).to receive(:[]).with('WHITELIST_DEPRECATIONS').and_return('')
|
27
|
+
expect(described_class.whitelist_deprecations?).to be_nil
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe '.ignorefile_path' do
|
32
|
+
it 'uses rails root' do
|
33
|
+
expect(described_class.ignorefile_path).to eq(Rails.root.join('config', 'deprecations.ignore'))
|
34
|
+
end
|
35
|
+
|
36
|
+
context 'when env var is set' do
|
37
|
+
before do
|
38
|
+
allow(ENV).to receive(:[]).with('UNCRUFT_IGNOREFILE_PATH').and_return('/path/to/file.txt')
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'uses env var' do
|
42
|
+
expect(described_class.ignorefile_path).to eq('/path/to/file.txt')
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
metadata
ADDED
@@ -0,0 +1,158 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: uncruft
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Nathan Griffith
|
8
|
+
- Chris Zega
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2019-04-30 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: railties
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - ">="
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: 4.2.0
|
21
|
+
type: :runtime
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: 4.2.0
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: appraisal
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - "~>"
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: 2.2.0
|
35
|
+
type: :development
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - "~>"
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: 2.2.0
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: rails
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
type: :development
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: rspec
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - "~>"
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: 3.7.0
|
63
|
+
type: :development
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - "~>"
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 3.7.0
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: rubocop-betterment
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - "~>"
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: 1.1.1
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - "~>"
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: 1.1.1
|
84
|
+
- !ruby/object:Gem::Dependency
|
85
|
+
name: timecop
|
86
|
+
requirement: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - "~>"
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: 0.9.1
|
91
|
+
type: :development
|
92
|
+
prerelease: false
|
93
|
+
version_requirements: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - "~>"
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: 0.9.1
|
98
|
+
description: A library to assist with clearing out Rails deprecation warnings and
|
99
|
+
upgrading Rails versions
|
100
|
+
email:
|
101
|
+
- nathan@betterment.com
|
102
|
+
executables: []
|
103
|
+
extensions: []
|
104
|
+
extra_rdoc_files: []
|
105
|
+
files:
|
106
|
+
- LICENSE
|
107
|
+
- README.md
|
108
|
+
- Rakefile
|
109
|
+
- lib/uncruft.rb
|
110
|
+
- lib/uncruft/deprecation_handler.rb
|
111
|
+
- lib/uncruft/railtie.rb
|
112
|
+
- lib/uncruft/version.rb
|
113
|
+
- lib/uncruft/warning.rb
|
114
|
+
- spec/dummy/config/application.rb
|
115
|
+
- spec/dummy/config/deprecations.ignore
|
116
|
+
- spec/dummy/log/test.log
|
117
|
+
- spec/examples.txt
|
118
|
+
- spec/spec_helper.rb
|
119
|
+
- spec/support/rails_root.rb
|
120
|
+
- spec/uncruft/deprecation_handler_spec.rb
|
121
|
+
- spec/uncruft/railtie_spec.rb
|
122
|
+
- spec/uncruft/warning_spec.rb
|
123
|
+
- spec/uncruft_spec.rb
|
124
|
+
homepage: https://github.com/Betterment/uncruft
|
125
|
+
licenses:
|
126
|
+
- MIT
|
127
|
+
metadata: {}
|
128
|
+
post_install_message:
|
129
|
+
rdoc_options: []
|
130
|
+
require_paths:
|
131
|
+
- lib
|
132
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
133
|
+
requirements:
|
134
|
+
- - ">="
|
135
|
+
- !ruby/object:Gem::Version
|
136
|
+
version: '0'
|
137
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
138
|
+
requirements:
|
139
|
+
- - ">="
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: '0'
|
142
|
+
requirements: []
|
143
|
+
rubyforge_project:
|
144
|
+
rubygems_version: 2.6.13
|
145
|
+
signing_key:
|
146
|
+
specification_version: 4
|
147
|
+
summary: A library to assist with Rails upgrades
|
148
|
+
test_files:
|
149
|
+
- spec/spec_helper.rb
|
150
|
+
- spec/dummy/config/deprecations.ignore
|
151
|
+
- spec/dummy/config/application.rb
|
152
|
+
- spec/dummy/log/test.log
|
153
|
+
- spec/examples.txt
|
154
|
+
- spec/uncruft/railtie_spec.rb
|
155
|
+
- spec/uncruft/warning_spec.rb
|
156
|
+
- spec/uncruft/deprecation_handler_spec.rb
|
157
|
+
- spec/support/rails_root.rb
|
158
|
+
- spec/uncruft_spec.rb
|