workarea-upgrade 3.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,30 @@
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
+ require 'date'
8
+ require 'tempfile'
9
+
10
+ load 'workarea/changelog.rake'
11
+
12
+ $LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
13
+ require 'workarea/upgrade/version'
14
+
15
+ desc "Release version #{Workarea::Upgrade::VERSION} of the gem"
16
+ task :release do
17
+ host = "https://#{ENV['BUNDLE_GEMS__WEBLINC__COM']}@gems.weblinc.com"
18
+
19
+ Rake::Task['workarea:changelog'].execute
20
+ system 'git add CHANGELOG.md'
21
+ system 'git commit -m "Update CHANGELOG"'
22
+
23
+ system "git tag -a v#{Workarea::Upgrade::VERSION} -m 'Tagging #{Workarea::Upgrade::VERSION}'"
24
+ system 'git push origin HEAD --follow-tags'
25
+
26
+ system "gem build workarea-upgrade.gemspec"
27
+ system "gem push workarea-upgrade-#{Workarea::Upgrade::VERSION}.gem #{host}"
28
+ system "gem push workarea-upgrade-#{Workarea::Upgrade::VERSION}.gem --host #{host}"
29
+ system "rm workarea-upgrade-#{Workarea::Upgrade::VERSION}.gem"
30
+ end
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env ruby
2
+ # This command will automatically be run when you run "rails" with Rails gems
3
+ # installed from the root of your application.
4
+
5
+ ENGINE_ROOT = File.expand_path('../..', __FILE__)
6
+ ENGINE_PATH = File.expand_path('../../lib/workarea/upgrade/engine', __FILE__)
7
+
8
+ # Set up gems listed in the Gemfile.
9
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
10
+ require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
11
+
12
+ require "action_controller/railtie"
13
+ require "action_view/railtie"
14
+ require "action_mailer/railtie"
15
+ require "rails/test_unit/railtie"
16
+ require "sprockets/railtie"
17
+
18
+ require 'rails/engine/commands'
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
4
+ require 'workarea/upgrade'
5
+ require 'workarea/upgrade/cli'
6
+
7
+ Workarea::Upgrade::CLI.start(ARGV)
@@ -0,0 +1,26 @@
1
+ require 'active_support/all'
2
+
3
+ require 'workarea'
4
+ require 'workarea/storefront'
5
+ require 'workarea/admin'
6
+
7
+ require 'thor'
8
+ require 'diffy'
9
+ require 'fileutils'
10
+ require 'bundler'
11
+ require 'rake'
12
+
13
+ require 'workarea/upgrade/engine'
14
+
15
+ module Workarea
16
+ module Upgrade
17
+ end
18
+ end
19
+
20
+ require 'workarea/upgrade/diff'
21
+ require 'workarea/upgrade/diff/gem_diff'
22
+ require 'workarea/upgrade/diff/workarea_file'
23
+ require 'workarea/upgrade/diff/current_app'
24
+
25
+ require 'workarea/upgrade/gemfile'
26
+ require 'workarea/upgrade/report'
@@ -0,0 +1,289 @@
1
+ module Workarea
2
+ module Upgrade
3
+ class CLI < Thor
4
+ include Thor::Actions
5
+
6
+ def self.source_root
7
+ Dir.pwd
8
+ end
9
+
10
+ default_task :prepare
11
+
12
+ desc 'prepare', 'Create a Gemfile.next'
13
+ long_desc <<~LONG_DESC
14
+ This plugin uses a special file, that must be present in your
15
+ application's root directory, called Gemfile.next. This file is like
16
+ a regular Gemfile but it contains a list of only the Workarea gems you
17
+ wish to upgrade your application to.
18
+
19
+ You can craft an artisanal Gemfile.next file yourself or use this
20
+ command to walk you through the creation process. If you choose to
21
+ handcraft your own bespoke Gemfile.next you can immediately use any of
22
+ the other commands offered, such as "report" or "diff".
23
+
24
+ If you want to walk through each of the versions available to you and
25
+ customize which to include you can use this "prepare" command to
26
+ generate or regenerate a Gemfile.next file.
27
+ LONG_DESC
28
+ option :latest,
29
+ aliases: :l, type: :boolean,
30
+ desc: 'Just use the latest Workarea gems for the upgrade'
31
+ def prepare
32
+ if gemfile_next.exist?
33
+ say "\nGemfile.next already exists in #{Dir.pwd}.", :green
34
+
35
+ if ask("\nWould you like to regenerate the file? [Yn]").casecmp?('n')
36
+ say "\nLooks like you're ready to upgrade!", :green
37
+ say 'Try running another command, like "diff" or "report":'
38
+ puts
39
+ invoke :help, [], {}
40
+ exit(0)
41
+ else
42
+ remove_file 'Gemfile.next'
43
+ remove_file 'Gemfile.next.lock'
44
+ invoke :prepare, [], {}
45
+ end
46
+ elsif gemfile_next.lockfile_exist?
47
+ remove_file 'Gemfile.next.lock'
48
+ end
49
+
50
+ say "\nPlease be patient; we're hacking The Gibson...", :yellow
51
+
52
+ unless gemfile.outdated.any?
53
+ say "\nYour application is already up to date!", :green
54
+ exit(0)
55
+ end
56
+
57
+ say "\nAvailable updates:", :yellow
58
+ gemfile.outdated.each { |g| say(" * #{g.first} (#{g.last})") }
59
+
60
+ chosen_gems = options[:latest] ? gemfile.outdated : choose_gems
61
+
62
+ copy_file 'Gemfile', 'Gemfile.next'
63
+
64
+ chosen_gems.each do |gem|
65
+ current_version = gemfile.installed.to_h[gem.first]
66
+ gsub_file 'Gemfile.next',
67
+ /#{gem.first}(['"].*)#{current_version}/,
68
+ "#{gem.first}\\1#{gem.last}"
69
+ end
70
+
71
+ if gemfile_next.check_install
72
+ invoke :report, [], {}
73
+ else
74
+ say "\nOh noes! Your Gemfile.next failed to install!", :red
75
+
76
+ puts
77
+ say <<~MESSAGE
78
+ This usually happens when you try to upgrade your project to a new
79
+ minor version. Workarea may be depending on different versions of
80
+ gems than you currently have listed in your Gemfile.
81
+
82
+ All this means is that we'll need a bit of human intervention for
83
+ this next part.
84
+
85
+ What you should do is manually edit the Gemfile.next that we've just
86
+ created in your project. After you've made some edits you can test
87
+ the Gemfile.next by running:
88
+
89
+ $ bundle install --gemfile Gemfile.next
90
+
91
+ Once you've resolved the dependency issues in your Gemfile.next you
92
+ can pick up where you left off by running:
93
+
94
+ $ bundle exec workarea_upgrade report
95
+ MESSAGE
96
+
97
+ say "\nGood luck!", :green
98
+ end
99
+ end
100
+
101
+ desc 'report', 'Display an overview of the complexity of the upgrade'
102
+ def report
103
+ prepared?
104
+
105
+ gems_to_ignore = Gemfile.diff(gemfile, gemfile_next).to_h.keys
106
+
107
+ diff = Diff.new(
108
+ gemfile_next.workarea_version,
109
+ options.merge(plugins: gemfile_next.plugins(gems_to_ignore).to_h)
110
+ )
111
+
112
+ report = Report.new(diff)
113
+
114
+ puts
115
+ puts '###############'
116
+ say 'Diff Statistics', :green
117
+ puts '###############'
118
+
119
+ display_report(report.diff_stats)
120
+
121
+ puts
122
+ puts '###############'
123
+ say ' Report Card', :green
124
+ puts '###############'
125
+
126
+ display_report(report.report_card_stats)
127
+
128
+ puts
129
+ puts '###############'
130
+ say ' Breakdown', :green
131
+ puts '###############'
132
+
133
+ display_report(report.breakdown_customized_stats)
134
+ display_report(report.breakdown_worst_files_stats)
135
+
136
+ puts
137
+ puts '###############'
138
+ say ' Next Steps', :green
139
+ puts '###############'
140
+
141
+ puts
142
+ puts "* View a full diff of all files that will be impacted by this upgrade:"
143
+ puts " $ bundle exec workarea_upgrade diff"
144
+
145
+ puts
146
+ puts "* Replace your Gemfile and Gemfile.lock with the new versions:"
147
+ puts " $ mv Gemfile.next Gemfile"
148
+ puts " $ mv Gemfile.next.lock Gemfile.lock"
149
+
150
+ puts
151
+ puts "* Compare release notes between your version and #{gemfile_next.workarea_version}:"
152
+ puts " https://developer.workarea.com/release-notes.html"
153
+
154
+ puts
155
+ puts "* If you're upgrading to a new minor be sure to read the appropriate Upgrade Guide:"
156
+ puts " https://developer.workarea.com/upgrade-guides.html"
157
+ end
158
+
159
+ desc 'diff', 'Output a diff of changes that will affect your project'
160
+ long_desc <<~LONG_DESC
161
+ The default diff displayed will be based on changes made to the Workarea
162
+ platform that will have an impact on the overridden or decorated files
163
+ found in your project.
164
+
165
+ It's purpose is to allow you to see what has changed in the underlying
166
+ platform and to make decisions based on whether or not a given change
167
+ should be incorporated into your app.
168
+
169
+ To see a full log of change between versions, not just the changes that
170
+ may or may not be relevant to your specific application, pass the
171
+ `--full` option to this command.
172
+ LONG_DESC
173
+ option :format,
174
+ aliases: :f,
175
+ type: :string,
176
+ default: 'color',
177
+ enum: %w[color html]
178
+ option :context,
179
+ alias: :c,
180
+ type: :numeric,
181
+ desc: 'The number of lines displayed around each change in the diff'
182
+ option :full,
183
+ type: :boolean,
184
+ desc: 'Display every change to Workarea, not just the impactful ones'
185
+ option :added,
186
+ type: :boolean,
187
+ desc: 'View a list of files that were added to Workarea'
188
+ option :removed,
189
+ type: :boolean,
190
+ desc: 'View a list of files that were removed from Workarea'
191
+ def diff
192
+ prepared?
193
+
194
+ gems_to_ignore = Gemfile.diff(gemfile, gemfile_next).to_h.keys
195
+
196
+ diff = Diff.new(
197
+ gemfile_next.workarea_version,
198
+ options.merge(plugins: gemfile_next.plugins(gems_to_ignore).to_h)
199
+ )
200
+
201
+ if options[:added]
202
+ puts diff.added.join("\n")
203
+ exit(0)
204
+ end
205
+
206
+ if options[:removed]
207
+ puts diff.removed.join("\n")
208
+ exit(0)
209
+ end
210
+
211
+ if options[:full]
212
+ handle_diff_output(diff.all.join, options[:format])
213
+ else
214
+ handle_diff_output(diff.for_current_app.join, options[:format])
215
+ end
216
+ end
217
+
218
+ private
219
+
220
+ def gemfile
221
+ @gemfile ||= Gemfile.new
222
+ end
223
+
224
+ def gemfile_next
225
+ @gemfile_next ||= Gemfile.new('Gemfile.next')
226
+ end
227
+
228
+ def prepared?
229
+ unless gemfile_next.exist?
230
+ say "\nGemfile.next was not found in #{Dir.pwd}", :red
231
+ say 'Preparing your application for upgrade...'
232
+ invoke :prepare, [], {}
233
+ end
234
+ end
235
+
236
+ def choose_gems
237
+ done = 'n'
238
+
239
+ while done.casecmp?('n')
240
+ say "\nYou can [C]ontinue, [s]kip, or enter a new version number:"
241
+
242
+ gems = gemfile.outdated.each_with_object([]) do |gem, memo|
243
+ choice = ask(" * #{gem.first} (#{gem.last})", :yellow)
244
+
245
+ next if choice.casecmp?('s')
246
+
247
+ if choice.casecmp?('c') || choice.empty?
248
+ memo << gem
249
+ else
250
+ memo << [gem.first, choice]
251
+ end
252
+ end
253
+
254
+ if gems.nil?
255
+ say('You must choose at least one gem to upgrade.', :red)
256
+ else
257
+ say("\nHere's what you chose:")
258
+ gems.each { |gem| say(" * #{gem.first} (#{gem.last})", :green) }
259
+
260
+ done = ask("\nWrite these gems to the Gemfile.next? [Ynq]")
261
+ exit(0) if done.casecmp?('q')
262
+ end
263
+ end
264
+
265
+ gems
266
+ end
267
+
268
+ def handle_diff_output(result, format)
269
+ if format.to_s == 'html'
270
+ puts <<-eos
271
+ <!doctype html>
272
+ <html>
273
+ <head><style>#{Diff::CSS}</style></head>
274
+ <body>#{result}</body>
275
+ </html>
276
+ eos
277
+ else
278
+ puts result
279
+ end
280
+ end
281
+
282
+ def display_report(stats)
283
+ stats.each do |stat|
284
+ say_status stat[:status], stat[:message], stat[:color]
285
+ end
286
+ end
287
+ end
288
+ end
289
+ end
@@ -0,0 +1,87 @@
1
+ module Workarea
2
+ module Upgrade
3
+ class Diff
4
+ CSS = <<-STYLE
5
+ .diff{overflow:auto;}
6
+ .diff ul{background:#fff;overflow:auto;font-size:13px;list-style:none;margin:0;padding:0;display:table;width:100%;}
7
+ .diff del, .diff ins{display:block;text-decoration:none;}
8
+ .diff li{padding:0; display:table-row;margin: 0;height:1em;}
9
+ .diff li.ins{background:#dfd; color:#080}
10
+ .diff li.del{background:#fee; color:#b00}
11
+ .diff li:hover{background:#ffc}
12
+ /* try 'whitespace:pre;' if you don't want lines to wrap */
13
+ .diff del, .diff ins, .diff span{white-space:pre-wrap;font-family:courier;}
14
+ .diff del strong{font-weight:normal;background:#fcc;}
15
+ .diff ins strong{font-weight:normal;background:#9f9;}
16
+ .diff li.diff-comment { background: none repeat scroll 0 0 gray; }
17
+ .diff li.diff-block-info { background: none repeat scroll 0 0 gray; }
18
+ STYLE
19
+
20
+ def initialize(core_to_version, options)
21
+ @core_to_version = core_to_version
22
+ @options = options
23
+ end
24
+
25
+ def plugins
26
+ @options[:plugins].presence || {}
27
+ end
28
+
29
+ def gem_diffs
30
+ @gem_diffs ||= gems.map do |gem, to_version|
31
+ from_path = find_from_path!(gem)
32
+ to_path = find_to_path!(gem, to_version)
33
+
34
+ GemDiff.new(
35
+ from_path,
36
+ to_path,
37
+ @options
38
+ )
39
+ end
40
+ end
41
+
42
+ %w(
43
+ all
44
+ for_current_app
45
+ added
46
+ removed
47
+ overridden
48
+ decorated
49
+ customized_files
50
+ ).each do |method|
51
+ define_method method do
52
+ gem_diffs.map(&method.to_sym).reduce(&:+)
53
+ end
54
+ end
55
+
56
+ def gems
57
+ %w(workarea-core workarea-storefront workarea-admin)
58
+ .each_with_object({}) { |gem, memo| memo[gem] = @core_to_version }
59
+ .merge(plugins)
60
+ .select { |gem, _version| find_from_path!(gem).present? }
61
+ end
62
+
63
+ def find_from_path!(gem)
64
+ Bundler.load.specs.find { |s| s.name == "#{gem}" }&.full_gem_path
65
+ end
66
+
67
+ def find_to_path!(gem, version)
68
+ unless version.to_s =~ /^(\d+\.)(\d+\.)(\d+)/
69
+ raise "#{version} is not a valid version number. Example format: 3.0.5"
70
+ end
71
+
72
+ result = "#{Gem.dir}/gems/#{gem}-#{version}"
73
+
74
+ if !File.directory?(result)
75
+ raise <<-eos.strip_heredoc
76
+
77
+ Couldn't find #{gem} v#{version} in installed gems!
78
+ Looked in #{result}
79
+ Try `gem install #{gem} -v #{version}`.
80
+ eos
81
+ end
82
+
83
+ result
84
+ end
85
+ end
86
+ end
87
+ end