ten_years_rails 0.2.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: cb75bc7f573b543ca6491b72f0289b4f107b93b8
4
- data.tar.gz: ede4f3a2877aee2dbb3d0034b6b99d3b570b0cc4
2
+ SHA256:
3
+ metadata.gz: c7429e7b5f2fa9af11ad43a9a4bd33f98758b78d38f83959d7723627fd1c2c9d
4
+ data.tar.gz: 41924ff861590eb505a50d97591ba8bee373de73aeffbd3d188f0094f278942c
5
5
  SHA512:
6
- metadata.gz: 0d98fba5b66b37ad5ba174f234ae2670c5908687c97db16339a61364a8b3ab343dfb698d90b25c9d75a8e5faec2d7eeab1fcea9045ee716b6b85c24ff9ca9625
7
- data.tar.gz: 1c230f4d09bd81f2fb89e346f32304b05c26be4a4c715a8d93e5d7b83135156ef3ec5cfce648805fc6c1bab91409d4eb91ae5b8b95bca8a0b1ce5c9c0ac41f6c
6
+ metadata.gz: 4fa4b901671e421a656c5992a1e756027ea281f2459f6d061f2ea90ac1c6009820a97f6b85b4854874137e83375599f0eda58d550d96c6861d385b3f28d31009
7
+ data.tar.gz: 7bdc9d37144c0b9fac45c5ff9a0a1d301d9a40d13cbfb6d0b94a3fd2bfdf51c1df1cd66104685b25371b0a4bba942a695a6ef334f1b261ff9cd73fa5472d8077
data/.gitignore CHANGED
@@ -7,5 +7,9 @@
7
7
  /spec/reports/
8
8
  /tmp/
9
9
 
10
+ .byebug_history
11
+
10
12
  # rspec failure tracking
11
13
  .rspec_status
14
+
15
+ .ruby-version
@@ -1,5 +1,6 @@
1
1
  sudo: false
2
2
  language: ruby
3
3
  rvm:
4
+ - 2.2.10
4
5
  - 2.3.3
5
6
  before_install: gem install bundler -v 1.16.1
@@ -1,78 +1,62 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ten_years_rails (0.1.0)
5
- actionview
6
- activesupport
7
- colorize (>= 0.8.1)
8
- rest-client (>= 2.0.2)
4
+ ten_years_rails (1.0.1)
5
+ actionview (~> 5.2.3)
6
+ rainbow (~> 3.0.0)
9
7
 
10
8
  GEM
11
9
  remote: https://rubygems.org/
12
10
  specs:
13
- actionview (5.2.0)
14
- activesupport (= 5.2.0)
11
+ actionview (5.2.4)
12
+ activesupport (= 5.2.4)
15
13
  builder (~> 3.1)
16
14
  erubi (~> 1.4)
17
15
  rails-dom-testing (~> 2.0)
18
16
  rails-html-sanitizer (~> 1.0, >= 1.0.3)
19
- activesupport (5.2.0)
17
+ activesupport (5.2.4)
20
18
  concurrent-ruby (~> 1.0, >= 1.0.2)
21
19
  i18n (>= 0.7, < 2)
22
20
  minitest (~> 5.1)
23
21
  tzinfo (~> 1.1)
24
22
  builder (3.2.3)
25
- colorize (0.8.1)
26
- concurrent-ruby (1.0.5)
27
- crass (1.0.4)
23
+ concurrent-ruby (1.1.5)
24
+ crass (1.0.5)
28
25
  diff-lcs (1.3)
29
- domain_name (0.5.20180417)
30
- unf (>= 0.0.5, < 1.0.0)
31
- erubi (1.7.1)
32
- http-cookie (1.0.3)
33
- domain_name (~> 0.5)
34
- i18n (1.0.1)
26
+ erubi (1.9.0)
27
+ i18n (1.7.0)
35
28
  concurrent-ruby (~> 1.0)
36
- loofah (2.2.2)
29
+ loofah (2.4.0)
37
30
  crass (~> 1.0.2)
38
31
  nokogiri (>= 1.5.9)
39
- mime-types (3.1)
40
- mime-types-data (~> 3.2015)
41
- mime-types-data (3.2016.0521)
42
- mini_portile2 (2.3.0)
43
- minitest (5.11.3)
44
- netrc (0.11.0)
45
- nokogiri (1.8.2)
46
- mini_portile2 (~> 2.3.0)
32
+ mini_portile2 (2.4.0)
33
+ minitest (5.13.0)
34
+ nokogiri (1.10.7)
35
+ mini_portile2 (~> 2.4.0)
47
36
  rails-dom-testing (2.0.3)
48
37
  activesupport (>= 4.2.0)
49
38
  nokogiri (>= 1.6)
50
- rails-html-sanitizer (1.0.4)
51
- loofah (~> 2.2, >= 2.2.2)
52
- rake (10.4.2)
53
- rest-client (2.0.2)
54
- http-cookie (>= 1.0.2, < 2.0)
55
- mime-types (>= 1.16, < 4.0)
56
- netrc (~> 0.8)
57
- rspec (3.7.0)
58
- rspec-core (~> 3.7.0)
59
- rspec-expectations (~> 3.7.0)
60
- rspec-mocks (~> 3.7.0)
61
- rspec-core (3.7.1)
62
- rspec-support (~> 3.7.0)
63
- rspec-expectations (3.7.0)
39
+ rails-html-sanitizer (1.3.0)
40
+ loofah (~> 2.3)
41
+ rainbow (3.0.0)
42
+ rake (10.5.0)
43
+ rspec (3.8.0)
44
+ rspec-core (~> 3.8.0)
45
+ rspec-expectations (~> 3.8.0)
46
+ rspec-mocks (~> 3.8.0)
47
+ rspec-core (3.8.2)
48
+ rspec-support (~> 3.8.0)
49
+ rspec-expectations (3.8.4)
64
50
  diff-lcs (>= 1.2.0, < 2.0)
65
- rspec-support (~> 3.7.0)
66
- rspec-mocks (3.7.0)
51
+ rspec-support (~> 3.8.0)
52
+ rspec-mocks (3.8.1)
67
53
  diff-lcs (>= 1.2.0, < 2.0)
68
- rspec-support (~> 3.7.0)
69
- rspec-support (3.7.1)
54
+ rspec-support (~> 3.8.0)
55
+ rspec-support (3.8.2)
70
56
  thread_safe (0.3.6)
57
+ timecop (0.9.1)
71
58
  tzinfo (1.2.5)
72
59
  thread_safe (~> 0.1)
73
- unf (0.1.4)
74
- unf_ext
75
- unf_ext (0.0.7.5)
76
60
 
77
61
  PLATFORMS
78
62
  ruby
@@ -82,6 +66,7 @@ DEPENDENCIES
82
66
  rake (~> 10.0)
83
67
  rspec (~> 3.0)
84
68
  ten_years_rails!
69
+ timecop (~> 0.9.1)
85
70
 
86
71
  BUNDLED WITH
87
- 1.16.1
72
+ 1.17.2
@@ -5,10 +5,11 @@
5
5
  #
6
6
  at_exit do
7
7
  require "optparse"
8
+ require "ten_years_rails"
8
9
 
9
10
  options = {}
10
11
  option_parser = OptionParser.new do |opts|
11
- opts.banner = <<~EOS
12
+ opts.banner = <<-EOS
12
13
  Usage: #{$0} [report-type] [options]
13
14
 
14
15
  report-type There are two report types available: `outdated` and `compatibility`
@@ -38,7 +39,7 @@ at_exit do
38
39
  begin
39
40
  option_parser.parse!
40
41
  rescue OptionParser::ParseError => e
41
- STDERR.puts e.message.red
42
+ STDERR.puts Rainbow(e.message).red
42
43
  puts option_parser
43
44
  exit 1
44
45
  end
@@ -46,9 +47,9 @@ at_exit do
46
47
  report_type = ARGV.first
47
48
 
48
49
  case report_type
49
- when "outdated" then BundleReport.outdated
50
+ when "outdated" then TenYearsRails::BundleReport.outdated
50
51
  else
51
- BundleReport.compatibility(rails_version: options.fetch(:rails_version, "5.0"), include_rails_gems: options.fetch(:include_rails_gems, false))
52
+ TenYearsRails::BundleReport.compatibility(rails_version: options.fetch(:rails_version, "5.0"), include_rails_gems: options.fetch(:include_rails_gems, false))
52
53
  end
53
54
  end
54
55
 
@@ -57,208 +58,3 @@ require "bundler/setup"
57
58
 
58
59
  require "action_view"
59
60
  require "active_support/core_ext/object/acts_like"
60
- require "colorize"
61
- require "cgi"
62
- require "erb"
63
- require "json"
64
- require "rest-client"
65
-
66
- class BundleReport
67
- def self.compatibility(rails_version:, include_rails_gems:)
68
- incompatible_gems = BundleReport::GemInfo.all.reject do |gem|
69
- gem.compatible_with_rails?(rails_version: rails_version) || (!include_rails_gems && gem.from_rails?)
70
- end.sort_by do |gem|
71
- [
72
- gem.latest_version.compatible_with_rails?(rails_version: rails_version) ? 0 : 1,
73
- gem.name
74
- ].join("-")
75
- end
76
-
77
- incompatible_gems_by_state = incompatible_gems.group_by { |gem| gem.state(rails_version) }
78
-
79
- template = <<~ERB
80
- <% if incompatible_gems_by_state[:latest_compatible] -%>
81
- <%= "=> Incompatible with Rails #{rails_version} (with new versions that are compatible):".white.bold %>
82
- <%= "These gems will need to be upgraded before upgrading to Rails #{rails_version}.".italic %>
83
-
84
- <% incompatible_gems_by_state[:latest_compatible].each do |gem| -%>
85
- <%= gem_header(gem) %> - upgrade to <%= gem.latest_version.version %>
86
- <% end -%>
87
-
88
- <% end -%>
89
- <% if incompatible_gems_by_state[:incompatible] -%>
90
- <%= "=> Incompatible with Rails #{rails_version} (with no new compatible versions):".white.bold %>
91
- <%= "These gems will need to be removed or replaced before upgrading to Rails #{rails_version}.".italic %>
92
-
93
- <% incompatible_gems_by_state[:incompatible].each do |gem| -%>
94
- <%= gem_header(gem) %> - new version, <%= gem.latest_version.version %>, is not compatible with Rails #{rails_version}
95
- <% end -%>
96
-
97
- <% end -%>
98
- <% if incompatible_gems_by_state[:no_new_version] -%>
99
- <%= "=> Incompatible with Rails #{rails_version} (with no new versions):".white.bold %>
100
- <%= "These gems will need to be upgraded by us or removed before upgrading to Rails #{rails_version}.".italic %>
101
- <%= "This list is likely to contain internal gems, like Cuddlefish.".italic %>
102
-
103
- <% incompatible_gems_by_state[:no_new_version].each do |gem| -%>
104
- <%= gem_header(gem) %> - new version not found
105
- <% end -%>
106
-
107
- <% end -%>
108
- <%= incompatible_gems.length.to_s.red %> gems incompatible with Rails <%= rails_version %>
109
- ERB
110
-
111
- puts ERB.new(template, nil, "-").result(binding)
112
- end
113
-
114
- def self.gem_header(_gem)
115
- header = "#{_gem.name} #{_gem.version}".bold
116
- header << " (loaded from git)".magenta if _gem.sourced_from_git?
117
- header
118
- end
119
-
120
- def self.outdated
121
- gems = BundleReport::GemInfo.all
122
- out_of_date_gems = gems.reject(&:up_to_date?).sort_by(&:created_at)
123
- percentage_out_of_date = ((out_of_date_gems.count / gems.count.to_f) * 100).round
124
- sourced_from_git = gems.select(&:sourced_from_git?)
125
-
126
- out_of_date_gems.each do |_gem|
127
- header = "#{_gem.name} #{_gem.version}"
128
-
129
- puts <<~MESSAGE
130
- #{header.bold.white}: released #{_gem.age} (latest version, #{_gem.latest_version.version}, released #{_gem.latest_version.age})
131
- MESSAGE
132
- end
133
-
134
- puts ""
135
- puts <<~MESSAGE
136
- #{"#{sourced_from_git.count}".yellow} gems are sourced from git
137
- #{"#{out_of_date_gems.length}".red} of the #{gems.count} gems are out-of-date (#{percentage_out_of_date}%)
138
- MESSAGE
139
- end
140
-
141
- class GemInfo
142
- include ActionView::Helpers::DateHelper
143
-
144
- class NullGemInfo < GemInfo
145
- def initialize; end
146
-
147
- def age
148
- "-"
149
- end
150
-
151
- def time_to_latest_version
152
- "-"
153
- end
154
-
155
- def created_at
156
- Time.now
157
- end
158
-
159
- def up_to_date?
160
- false
161
- end
162
-
163
- def version
164
- "NOT FOUND"
165
- end
166
-
167
- def unsatisfied_rails_dependencies(*)
168
- ["unknown"]
169
- end
170
-
171
- def state(_)
172
- :null
173
- end
174
- end
175
-
176
- def self.all
177
- Gem::Specification.each.map do |gem_specification|
178
- new(gem_specification)
179
- end
180
- end
181
-
182
- attr_reader :gem_specification, :version, :name
183
- def initialize(gem_specification)
184
- @gem_specification = gem_specification
185
- @version = gem_specification.version
186
- @name = gem_specification.name
187
- end
188
-
189
- def age
190
- "#{time_ago_in_words(created_at)} ago"
191
- end
192
-
193
- def sourced_from_git?
194
- !!gem_specification.git_version
195
- end
196
-
197
- def time_to_latest_version
198
- distance_of_time_in_words(created_at, latest_version.created_at)
199
- end
200
-
201
- def created_at
202
- @created_at ||= gem_specification.date
203
- end
204
-
205
- def up_to_date?
206
- version == latest_version.version
207
- end
208
-
209
- def state(rails_version)
210
- if compatible_with_rails?(rails_version: rails_version)
211
- :compatible
212
- elsif latest_version.compatible_with_rails?(rails_version: rails_version)
213
- :latest_compatible
214
- elsif latest_version.version == "NOT FOUND"
215
- :no_new_version
216
- else
217
- :incompatible
218
- end
219
- end
220
-
221
- def latest_version
222
- @latest_version ||= begin
223
- latest_gem_specification = Gem.latest_spec_for(name)
224
- if latest_gem_specification
225
- GemInfo.new(latest_gem_specification)
226
- else
227
- NullGemInfo.new
228
- end
229
- end
230
- end
231
-
232
- def compatible_with_rails?(rails_version: Gem::Version.new("5.0"))
233
- unsatisfied_rails_dependencies(rails_version: rails_version).empty?
234
- end
235
-
236
- def unsatisfied_rails_dependencies(rails_version:)
237
- rails_dependencies = gem_specification.runtime_dependencies.select {|dependency| rails_gems.include?(dependency.name) }
238
-
239
- rails_dependencies.reject do |rails_dependency|
240
- rails_dependency.requirement.satisfied_by?(Gem::Version.new(rails_version))
241
- end
242
- end
243
-
244
- def from_rails?
245
- rails_gems.include?(name)
246
- end
247
-
248
- private def rails_gems
249
- [
250
- "rails",
251
- "activemodel",
252
- "activerecord",
253
- "actionmailer",
254
- "actioncable",
255
- "actionpack",
256
- "actionview",
257
- "activejob",
258
- "activestorage",
259
- "activesupport",
260
- "railties",
261
- ]
262
- end
263
- end
264
- end
@@ -1,10 +1,12 @@
1
1
  #!/usr/bin/env ruby
2
2
  require "json"
3
- require "colorize"
3
+ require "rainbow"
4
4
  require "optparse"
5
5
  require "set"
6
6
 
7
- def run_tests(deprecation_warnings, tracker_mode:, next_mode:)
7
+ def run_tests(deprecation_warnings, opts = {})
8
+ tracker_mode = opts[:tracker_mode]
9
+ next_mode = opts[:next_mode]
8
10
  rspec_command = if next_mode
9
11
  "bin/next rspec"
10
12
  else
@@ -16,7 +18,8 @@ def run_tests(deprecation_warnings, tracker_mode:, next_mode:)
16
18
  exec command
17
19
  end
18
20
 
19
- def print_info(deprecation_warnings, verbose: false)
21
+ def print_info(deprecation_warnings, opts = {})
22
+ verbose = !!opts[:verbose]
20
23
  frequency_by_message = deprecation_warnings.each_with_object({}) do |(test_file, messages), hash|
21
24
  messages.each do |message|
22
25
  hash[message] ||= { test_files: Set.new, occurrences: 0 }
@@ -27,16 +30,16 @@ def print_info(deprecation_warnings, verbose: false)
27
30
 
28
31
  puts "Ten most common deprecation warnings:".underline
29
32
  frequency_by_message.take(10).each do |message, data|
30
- puts "Occurrences: #{data.fetch(:occurrences)}".bold
33
+ puts Rainbow("Occurrences: #{data.fetch(:occurrences)}").bold
31
34
  puts "Test files: #{data.fetch(:test_files).to_a.join(" ")}" if verbose
32
- puts message.red
35
+ puts Rainbow(message).red
33
36
  puts "----------"
34
37
  end
35
38
  end
36
39
 
37
40
  options = {}
38
41
  option_parser = OptionParser.new do |opts|
39
- opts.banner = <<~MESSAGE
42
+ opts.banner = <<-MESSAGE
40
43
  Usage: #{__FILE__.to_s} [options] [mode]
41
44
 
42
45
  Parses the deprecation warning shitlist and show info or run tests.
@@ -101,10 +104,10 @@ case options.fetch(:mode, "info")
101
104
  when "run" then run_tests(deprecation_warnings, next_mode: options[:next], tracker_mode: options[:tracker_mode])
102
105
  when "info" then print_info(deprecation_warnings, verbose: options[:verbose])
103
106
  when nil
104
- STDERR.puts "Must pass a mode: run or info".red
107
+ STDERR.puts Rainbow("Must pass a mode: run or info").red
105
108
  puts option_parser
106
109
  exit 1
107
110
  else
108
- STDERR.puts "Unknown mode: #{options[:mode]}".red
111
+ STDERR.puts Rainbow("Unknown mode: #{options[:mode]}").red
109
112
  exit 1
110
113
  end
@@ -1,6 +1,5 @@
1
1
  #!/bin/bash
2
2
  if [[ "${@}" == "--init" ]]; then
3
- echo "doing a thing"
4
3
  # Add next? top of Gemfile
5
4
  cat <<-STRING > Gemfile.tmp
6
5
  def next?
@@ -11,6 +10,19 @@ STRING
11
10
  mv Gemfile.tmp Gemfile
12
11
 
13
12
  ln -s Gemfile Gemfile.next
13
+ echo <<-MESSAGE
14
+ Created Gemfile.next (a symlink to your Gemfile). Your Gemfile has been modified to support dual-booting!
15
+
16
+ There's just one more step: modify your Gemfile to use a newer version of Rails using the \`next?\` helper method.
17
+
18
+ For example, here's how to go from 5.2.3 to 6.0:
19
+
20
+ if next?
21
+ gem "rails", "6.0.0"
22
+ else
23
+ gem "rails", "5.2.3"
24
+ end
25
+ MESSAGE
14
26
  exit $?
15
27
  fi
16
28
 
@@ -1,3 +1,4 @@
1
+ require "rainbow"
1
2
  require "json"
2
3
 
3
4
  # A shitlist for deprecation warnings during test runs. It has two modes: "save" and "compare"
@@ -28,11 +29,24 @@ class DeprecationTracker
28
29
 
29
30
  # There are two forms of the `warn` method: one for class Kernel and one for instances of Kernel (i.e., every Object)
30
31
  Object.prepend(KernelWarnTracker)
31
- Kernel.singleton_class.prepend(KernelWarnTracker)
32
32
 
33
- def self.track_rspec(rspec_config, shitlist_path:, mode:, transform_message: nil)
33
+ # Ruby 2.2 and lower doesn't appear to allow overriding of Kernel.warn using `singleton_class.prepend`.
34
+ if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("2.3.0")
35
+ Kernel.singleton_class.prepend(KernelWarnTracker)
36
+ else
37
+ def Kernel.warn(*args, &block)
38
+ Object.warn(*args, &block)
39
+ end
40
+ end
41
+
42
+ def self.track_rspec(rspec_config, opts = {})
43
+ shitlist_path = opts[:shitlist_path]
44
+ mode = opts[:mode]
45
+ transform_message = opts[:transform_message]
34
46
  deprecation_tracker = DeprecationTracker.new(shitlist_path, transform_message)
35
- ActiveSupport::Deprecation.behavior << -> (message, _callstack) { deprecation_tracker.add(message) }
47
+ if defined?(ActiveSupport)
48
+ ActiveSupport::Deprecation.behavior << -> (message, _callstack, _deprecation_horizon, _gem_name) { deprecation_tracker.add(message) }
49
+ end
36
50
  KernelWarnTracker.callbacks << -> (message) { deprecation_tracker.add(message) }
37
51
 
38
52
  rspec_config.around do |example|
@@ -85,7 +99,7 @@ class DeprecationTracker
85
99
  end
86
100
 
87
101
  if changed_buckets.length > 0
88
- message = <<~MESSAGE.red
102
+ message = Rainbow(<<-MESSAGE).red
89
103
  ⚠️ Deprecation warnings have changed!
90
104
 
91
105
  Code called by the following spec files is now generating different deprecation warnings:
@@ -118,7 +132,7 @@ class DeprecationTracker
118
132
  new_shitlist = create_temp_shitlist
119
133
  FileUtils.cp(new_shitlist.path, shitlist_path)
120
134
  ensure
121
- new_shitlist&.delete
135
+ new_shitlist.delete if new_shitlist
122
136
  end
123
137
 
124
138
  def create_temp_shitlist
@@ -1,4 +1,6 @@
1
+ require "ten_years_rails/gem_info"
1
2
  require "ten_years_rails/version"
3
+ require "ten_years_rails/bundle_report"
2
4
  require "deprecation_tracker"
3
5
 
4
6
  module TenYearsRails
@@ -0,0 +1,82 @@
1
+ require "rainbow"
2
+ require "cgi"
3
+ require "erb"
4
+ require "json"
5
+
6
+ module TenYearsRails
7
+ class BundleReport
8
+ def self.compatibility(rails_version:, include_rails_gems:)
9
+ incompatible_gems = TenYearsRails::GemInfo.all.reject do |gem|
10
+ gem.compatible_with_rails?(rails_version: rails_version) || (!include_rails_gems && gem.from_rails?)
11
+ end.sort_by do |gem|
12
+ [
13
+ gem.latest_version.compatible_with_rails?(rails_version: rails_version) ? 0 : 1,
14
+ gem.name
15
+ ].join("-")
16
+ end
17
+
18
+ incompatible_gems_by_state = incompatible_gems.group_by { |gem| gem.state(rails_version) }
19
+
20
+ template = <<~ERB
21
+ <% if incompatible_gems_by_state[:latest_compatible] -%>
22
+ <%= Rainbow("=> Incompatible with Rails #{rails_version} (with new versions that are compatible):").white.bold %>
23
+ <%= Rainbow("These gems will need to be upgraded before upgrading to Rails #{rails_version}.").italic %>
24
+
25
+ <% incompatible_gems_by_state[:latest_compatible].each do |gem| -%>
26
+ <%= gem_header(gem) %> - upgrade to <%= gem.latest_version.version %>
27
+ <% end -%>
28
+
29
+ <% end -%>
30
+ <% if incompatible_gems_by_state[:incompatible] -%>
31
+ <%= Rainbow("=> Incompatible with Rails #{rails_version} (with no new compatible versions):").white.bold %>
32
+ <%= Rainbow("These gems will need to be removed or replaced before upgrading to Rails #{rails_version}.").italic %>
33
+
34
+ <% incompatible_gems_by_state[:incompatible].each do |gem| -%>
35
+ <%= gem_header(gem) %> - new version, <%= gem.latest_version.version %>, is not compatible with Rails #{rails_version}
36
+ <% end -%>
37
+
38
+ <% end -%>
39
+ <% if incompatible_gems_by_state[:no_new_version] -%>
40
+ <%= Rainbow("=> Incompatible with Rails #{rails_version} (with no new versions):").white.bold %>
41
+ <%= Rainbow("These gems will need to be upgraded by us or removed before upgrading to Rails #{rails_version}.").italic %>
42
+ <%= Rainbow("This list is likely to contain internal gems, like Cuddlefish.").italic %>
43
+
44
+ <% incompatible_gems_by_state[:no_new_version].each do |gem| -%>
45
+ <%= gem_header(gem) %> - new version not found
46
+ <% end -%>
47
+
48
+ <% end -%>
49
+ <%= Rainbow(incompatible_gems.length.to_s).red %> gems incompatible with Rails <%= rails_version %>
50
+ ERB
51
+
52
+ puts ERB.new(template, nil, "-").result(binding)
53
+ end
54
+
55
+ def self.gem_header(_gem)
56
+ header = "#{_gem.name} #{_gem.version}".bold
57
+ header << " (loaded from git)".magenta if _gem.sourced_from_git?
58
+ header
59
+ end
60
+
61
+ def self.outdated
62
+ gems = TenYearsRails::GemInfo.all
63
+ out_of_date_gems = gems.reject(&:up_to_date?).sort_by(&:created_at)
64
+ percentage_out_of_date = ((out_of_date_gems.count / gems.count.to_f) * 100).round
65
+ sourced_from_git = gems.select(&:sourced_from_git?)
66
+
67
+ out_of_date_gems.each do |_gem|
68
+ header = "#{_gem.name} #{_gem.version}"
69
+
70
+ puts <<~MESSAGE
71
+ #{Rainbow(header).bold.white}: released #{_gem.age} (latest version, #{_gem.latest_version.version}, released #{_gem.latest_version.age})
72
+ MESSAGE
73
+ end
74
+
75
+ puts ""
76
+ puts <<~MESSAGE
77
+ #{Rainbow(sourced_from_git.count.to_s).yellow} gems are sourced from git
78
+ #{Rainbow(out_of_date_gems.length.to_s).red} of the #{gems.count} gems are out-of-date (#{percentage_out_of_date}%)
79
+ MESSAGE
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,129 @@
1
+ begin
2
+ require "action_view"
3
+ rescue LoadError
4
+ puts "ActionView not available"
5
+ end
6
+
7
+ module TenYearsRails
8
+ class GemInfo
9
+ if defined?(ActionView)
10
+ include ActionView::Helpers::DateHelper
11
+ end
12
+
13
+ class NullGemInfo < GemInfo
14
+ def initialize; end
15
+
16
+ def age
17
+ "-"
18
+ end
19
+
20
+ def created_at
21
+ Time.now
22
+ end
23
+
24
+ def up_to_date?
25
+ false
26
+ end
27
+
28
+ def version
29
+ "NOT FOUND"
30
+ end
31
+
32
+ def unsatisfied_rails_dependencies(*)
33
+ ["unknown"]
34
+ end
35
+
36
+ def state(_)
37
+ :null
38
+ end
39
+ end
40
+
41
+ def self.all
42
+ Gem::Specification.each.map do |gem_specification|
43
+ new(gem_specification)
44
+ end
45
+ end
46
+
47
+ attr_reader :gem_specification, :version, :name
48
+ def initialize(gem_specification)
49
+ @gem_specification = gem_specification
50
+ @version = gem_specification.version
51
+ @name = gem_specification.name
52
+ end
53
+
54
+ def age
55
+ if respond_to?(:time_ago_in_words)
56
+ "#{time_ago_in_words(created_at)} ago"
57
+ else
58
+ created_at.strftime("%b %e, %Y")
59
+ end
60
+ end
61
+
62
+ def sourced_from_git?
63
+ !!gem_specification.git_version
64
+ end
65
+
66
+ def created_at
67
+ @created_at ||= gem_specification.date
68
+ end
69
+
70
+ def up_to_date?
71
+ version == latest_version.version
72
+ end
73
+
74
+ def state(rails_version)
75
+ if compatible_with_rails?(rails_version: rails_version)
76
+ :compatible
77
+ elsif latest_version.compatible_with_rails?(rails_version: rails_version)
78
+ :latest_compatible
79
+ elsif latest_version.version == "NOT FOUND"
80
+ :no_new_version
81
+ else
82
+ :incompatible
83
+ end
84
+ end
85
+
86
+ def latest_version
87
+ @latest_version ||= begin
88
+ latest_gem_specification = Gem.latest_spec_for(name)
89
+ if latest_gem_specification
90
+ GemInfo.new(latest_gem_specification)
91
+ else
92
+ NullGemInfo.new
93
+ end
94
+ end
95
+ end
96
+
97
+ def compatible_with_rails?(rails_version: Gem::Version.new("5.0"))
98
+ unsatisfied_rails_dependencies(rails_version: rails_version).empty?
99
+ end
100
+
101
+ def unsatisfied_rails_dependencies(rails_version:)
102
+ rails_dependencies = gem_specification.runtime_dependencies.select {|dependency| rails_gems.include?(dependency.name) }
103
+
104
+ rails_dependencies.reject do |rails_dependency|
105
+ rails_dependency.requirement.satisfied_by?(Gem::Version.new(rails_version))
106
+ end
107
+ end
108
+
109
+ def from_rails?
110
+ rails_gems.include?(name)
111
+ end
112
+
113
+ private def rails_gems
114
+ [
115
+ "rails",
116
+ "activemodel",
117
+ "activerecord",
118
+ "actionmailer",
119
+ "actioncable",
120
+ "actionpack",
121
+ "actionview",
122
+ "activejob",
123
+ "activestorage",
124
+ "activesupport",
125
+ "railties",
126
+ ]
127
+ end
128
+ end
129
+ end
@@ -1,3 +1,3 @@
1
1
  module TenYearsRails
2
- VERSION = "0.2.0"
2
+ VERSION = "1.0.1"
3
3
  end
@@ -6,13 +6,16 @@ require "ten_years_rails/version"
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "ten_years_rails"
8
8
  spec.version = TenYearsRails::VERSION
9
- spec.authors = ["Jordan Raine"]
10
- spec.email = ["jnraine@gmail.com"]
9
+ spec.authors = ["Jordan Raine", "Ernesto Tagwerker"]
10
+ spec.email = ["jnraine@gmail.com", "ernesto@ombulabs.com"]
11
11
 
12
12
  spec.summary = %q{Companion code to Ten Years of Rails Upgrades}
13
+ spec.description = %q{A set of handy tools to upgrade your Rails application and keep it up to date}
13
14
  spec.homepage = "https://github.com/clio/ten_years_rails"
14
15
  spec.license = "MIT"
15
16
 
17
+ spec.required_ruby_version = ">= 2.3.0"
18
+
16
19
  spec.files = `git ls-files -z`.split("\x0").reject do |f|
17
20
  f.match(%r{^(test|spec|features)/})
18
21
  end
@@ -20,11 +23,10 @@ Gem::Specification.new do |spec|
20
23
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
24
  spec.require_paths = ["lib"]
22
25
 
23
- spec.add_dependency "actionview"
24
- spec.add_dependency "activesupport"
25
- spec.add_dependency "colorize", ">= 0.8.1"
26
- spec.add_dependency "rest-client", ">= 2.0.2"
26
+ spec.add_dependency "rainbow", "~> 3.0.0"
27
27
  spec.add_development_dependency "bundler", "~> 1.16"
28
28
  spec.add_development_dependency "rake", "~> 10.0"
29
29
  spec.add_development_dependency "rspec", "~> 3.0"
30
+ spec.add_development_dependency "timecop", "~> 0.9.1"
31
+ spec.add_runtime_dependency "actionview", "~> 5.2.3"
30
32
  end
metadata CHANGED
@@ -1,116 +1,105 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ten_years_rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jordan Raine
8
+ - Ernesto Tagwerker
8
9
  autorequire:
9
10
  bindir: exe
10
11
  cert_chain: []
11
- date: 2018-10-21 00:00:00.000000000 Z
12
+ date: 2019-12-13 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
- name: actionview
15
+ name: rainbow
15
16
  requirement: !ruby/object:Gem::Requirement
16
17
  requirements:
17
- - - ">="
18
- - !ruby/object:Gem::Version
19
- version: '0'
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - ">="
25
- - !ruby/object:Gem::Version
26
- version: '0'
27
- - !ruby/object:Gem::Dependency
28
- name: activesupport
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
18
+ - - "~>"
32
19
  - !ruby/object:Gem::Version
33
- version: '0'
20
+ version: 3.0.0
34
21
  type: :runtime
35
22
  prerelease: false
36
23
  version_requirements: !ruby/object:Gem::Requirement
37
24
  requirements:
38
- - - ">="
25
+ - - "~>"
39
26
  - !ruby/object:Gem::Version
40
- version: '0'
27
+ version: 3.0.0
41
28
  - !ruby/object:Gem::Dependency
42
- name: colorize
29
+ name: bundler
43
30
  requirement: !ruby/object:Gem::Requirement
44
31
  requirements:
45
- - - ">="
32
+ - - "~>"
46
33
  - !ruby/object:Gem::Version
47
- version: 0.8.1
48
- type: :runtime
34
+ version: '1.16'
35
+ type: :development
49
36
  prerelease: false
50
37
  version_requirements: !ruby/object:Gem::Requirement
51
38
  requirements:
52
- - - ">="
39
+ - - "~>"
53
40
  - !ruby/object:Gem::Version
54
- version: 0.8.1
41
+ version: '1.16'
55
42
  - !ruby/object:Gem::Dependency
56
- name: rest-client
43
+ name: rake
57
44
  requirement: !ruby/object:Gem::Requirement
58
45
  requirements:
59
- - - ">="
46
+ - - "~>"
60
47
  - !ruby/object:Gem::Version
61
- version: 2.0.2
62
- type: :runtime
48
+ version: '10.0'
49
+ type: :development
63
50
  prerelease: false
64
51
  version_requirements: !ruby/object:Gem::Requirement
65
52
  requirements:
66
- - - ">="
53
+ - - "~>"
67
54
  - !ruby/object:Gem::Version
68
- version: 2.0.2
55
+ version: '10.0'
69
56
  - !ruby/object:Gem::Dependency
70
- name: bundler
57
+ name: rspec
71
58
  requirement: !ruby/object:Gem::Requirement
72
59
  requirements:
73
60
  - - "~>"
74
61
  - !ruby/object:Gem::Version
75
- version: '1.16'
62
+ version: '3.0'
76
63
  type: :development
77
64
  prerelease: false
78
65
  version_requirements: !ruby/object:Gem::Requirement
79
66
  requirements:
80
67
  - - "~>"
81
68
  - !ruby/object:Gem::Version
82
- version: '1.16'
69
+ version: '3.0'
83
70
  - !ruby/object:Gem::Dependency
84
- name: rake
71
+ name: timecop
85
72
  requirement: !ruby/object:Gem::Requirement
86
73
  requirements:
87
74
  - - "~>"
88
75
  - !ruby/object:Gem::Version
89
- version: '10.0'
76
+ version: 0.9.1
90
77
  type: :development
91
78
  prerelease: false
92
79
  version_requirements: !ruby/object:Gem::Requirement
93
80
  requirements:
94
81
  - - "~>"
95
82
  - !ruby/object:Gem::Version
96
- version: '10.0'
83
+ version: 0.9.1
97
84
  - !ruby/object:Gem::Dependency
98
- name: rspec
85
+ name: actionview
99
86
  requirement: !ruby/object:Gem::Requirement
100
87
  requirements:
101
88
  - - "~>"
102
89
  - !ruby/object:Gem::Version
103
- version: '3.0'
104
- type: :development
90
+ version: 5.2.3
91
+ type: :runtime
105
92
  prerelease: false
106
93
  version_requirements: !ruby/object:Gem::Requirement
107
94
  requirements:
108
95
  - - "~>"
109
96
  - !ruby/object:Gem::Version
110
- version: '3.0'
111
- description:
97
+ version: 5.2.3
98
+ description: A set of handy tools to upgrade your Rails application and keep it up
99
+ to date
112
100
  email:
113
101
  - jnraine@gmail.com
102
+ - ernesto@ombulabs.com
114
103
  executables:
115
104
  - bundle_report
116
105
  - deprecations
@@ -138,6 +127,8 @@ files:
138
127
  - exe/next.sh
139
128
  - lib/deprecation_tracker.rb
140
129
  - lib/ten_years_rails.rb
130
+ - lib/ten_years_rails/bundle_report.rb
131
+ - lib/ten_years_rails/gem_info.rb
141
132
  - lib/ten_years_rails/version.rb
142
133
  - ten_years_rails.gemspec
143
134
  homepage: https://github.com/clio/ten_years_rails
@@ -152,7 +143,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
152
143
  requirements:
153
144
  - - ">="
154
145
  - !ruby/object:Gem::Version
155
- version: '0'
146
+ version: 2.3.0
156
147
  required_rubygems_version: !ruby/object:Gem::Requirement
157
148
  requirements:
158
149
  - - ">="
@@ -160,7 +151,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
160
151
  version: '0'
161
152
  requirements: []
162
153
  rubyforge_project:
163
- rubygems_version: 2.6.14
154
+ rubygems_version: 2.7.9
164
155
  signing_key:
165
156
  specification_version: 4
166
157
  summary: Companion code to Ten Years of Rails Upgrades