Share
Embed
Upgrade Rails 101: The Roadmap to Smooth Upgrades (Southeast Ruby '19)
I presented this workshop on August 1st, 2019 at Southeast Ruby.
It details a series of exercises for crafting a Rails Upgrade roadmap.
The main goal of the workshop is to explain what our process looks like at fastruby.io and how you can apply to a sample Rails application.
Thanks to the conference organizers, sponsors, and attendees! :)
Ernesto Tagwerker
August 01, 2019
Transcript
127 slides
-
@etagwerker | #RailsUpgrades | https://fastruby.io/upgrade Upgrade Rails 101 The Roadmap
to Smooth Upgrades Southeast Ruby 2019 -
@etagwerker | #RailsUpgrades | https://fastruby.io/upgrade 15 $ git clone \
[email protected]:fastruby/e-petitions.git $ cd e-petitions $ git fetch origin docker:docker $ git checkout docker -
@etagwerker | #RailsUpgrades | https://fastruby.io/upgrade 16 $ docker-compose up -d
$ docker-compose exec app \ ./bin/docker-setup -
@etagwerker | #RailsUpgrades | https://fastruby.io/upgrade 17 $ docker-compose exec app
\ rspec spec/models/admin_user_spec.rb ... Finished in 22.24 seconds (files took 7.65 seconds to load) 81 examples, 0 failures -
@etagwerker | #RailsUpgrades | https://fastruby.io/upgrade Exercise #1: Check Pre-Requisites Time:
15 minutes https://fastruby.io/upgrade#1 https://fastruby.io/upgrade#2 https://fastruby.io/upgrade#3 -
@etagwerker | #RailsUpgrades | https://fastruby.io/upgrade - “Upgrading Rails is easy,
right?” - “Right, right, easy…” -
@etagwerker | #RailsUpgrades | https://fastruby.io/upgrade 27 # Gemfile group :test
do gem 'simplecov', require: false end -
@etagwerker | #RailsUpgrades | https://fastruby.io/upgrade 28 # spec/spec_helper.rb if ENV['COVERAGE']
== 'true' require 'simplecov' SimpleCov.start 'rails' end -
@etagwerker | #RailsUpgrades | https://fastruby.io/upgrade 29 $ docker-compose run -e
COVERAGE=true app rspec spec/models/ -
@etagwerker | #RailsUpgrades | https://fastruby.io/upgrade 31 Exercise #2: Check Test
Coverage Time: 15 minutes https://fastruby.io/upgrade#4 -
@etagwerker | #RailsUpgrades | https://fastruby.io/upgrade 41 # Gemfile (fixed version)
source 'https://rubygems.org' gem 'rails', '4.2.7' -
@etagwerker | #RailsUpgrades | https://fastruby.io/upgrade 42 $ bundle update $
cat Gemfile.lock | grep rails rails (4.2.7) -
@etagwerker | #RailsUpgrades | https://fastruby.io/upgrade 43 # Gemfile (pessimistic versions)
source 'https://rubygems.org' gem 'rails', '~> 4.2.7' -
@etagwerker | #RailsUpgrades | https://fastruby.io/upgrade 44 $ bundle update $
cat Gemfile.lock | grep rails rails (4.2.11.1) -
@etagwerker | #RailsUpgrades | https://fastruby.io/upgrade 48 $ docker-compose exec app
bundle outdated Fetching gem metadata from https://rubygems.org/. Resolving dependencies..... Outdated gems included in the bundle: * actionmailer (newest 5.2.3, installed 4.2.11.1) * actionpack (newest 5.2.3, installed 4.2.11.1) * actionview (newest 5.2.3, installed 4.2.11.1) * activejob (newest 5.2.3, installed 4.2.11.1) * activemodel (newest 5.2.3, installed 4.2.11.1) * activerecord (newest 5.2.3, installed 4.2.11.1) * activesupport (newest 5.2.3, installed 4.2.11.1) ... -
@etagwerker | #RailsUpgrades | https://fastruby.io/upgrade 49 # Gemfile group :development
do gem 'next_rails' end -
@etagwerker | #RailsUpgrades | https://fastruby.io/upgrade $ docker-compose exec app \
bundle_report outdated ... aws-sdk 2.11.314: released 19 days ago (latest version, 3.0.1, released almost 2 years ago) 0 gems are sourced from git 44 of the 139 gems are out-of-date (32%) -
@etagwerker | #RailsUpgrades | https://fastruby.io/upgrade For every fixed dependency declaration:
- Turn it into a pessimistic declaration 52 -
@etagwerker | #RailsUpgrades | https://fastruby.io/upgrade For every fixed dependency declaration
we change: 53 $ docker-compose down --volumes $ docker-compose up --build -d -
@etagwerker | #RailsUpgrades | https://fastruby.io/upgrade For every fixed dependency declaration
we change: 54 $ docker-compose exec app \ rspec spec/lib/atomic_dalli_store_spec.rb -
@etagwerker | #RailsUpgrades | https://fastruby.io/upgrade Does your build pass? -
Submit a PR - Create a story 55 -
@etagwerker | #RailsUpgrades | https://fastruby.io/upgrade 57 Exercise #3: Pessimistic Dependencies
Time: 10 minutes https://fastruby.io/upgrade#5 https://fastruby.io/upgrade#6 -
@etagwerker | #RailsUpgrades | https://fastruby.io/upgrade 63 # Gemfile group :development
do gem 'next_rails' end -
@etagwerker | #RailsUpgrades | https://fastruby.io/upgrade 64 $ docker-compose exec app
next --init Created Gemfile.next (a symlink to your Gemfile). Your Gemfile has been modified to support dual-booting! There's just one more step: modify your Gemfile to use a newer version of Rails using the `next?` helper method. For example, here's how to go from 5.2.3 to 6.0: if next? gem "rails", "6.0.0" else gem "rails", "5.2.3" end -
@etagwerker | #RailsUpgrades | https://fastruby.io/upgrade 65 # Gemfile def next?
File.basename(__FILE__) == "Gemfile.next" end source ‘https://rubygems.org' gem 'rails', '4.2.11.1' -
@etagwerker | #RailsUpgrades | https://fastruby.io/upgrade 66 # Gemfile if next?
gem 'rails', '~> 5.0.7' else gem 'rails', '4.2.11.1' end -
@etagwerker | #RailsUpgrades | https://fastruby.io/upgrade 67 $ docker-compose exec \
next bundle install $ cat Gemfile.next.lock -
@etagwerker | #RailsUpgrades | https://fastruby.io/upgrade 68 # Dockerfile COPY Gemfile
Gemfile.lock ./ COPY Gemfile.next Gemfile.next.lock ./ RUN gem install bundler -v=1.17.3 RUN bundle install RUN next bundle install COPY . . -
@etagwerker | #RailsUpgrades | https://fastruby.io/upgrade 69 $ docker-compose down $
docker-compose up --build -d $ docker-compose exec app \ ./bin/docker-setup -
@etagwerker | #RailsUpgrades | https://fastruby.io/upgrade 71 $ docker-compose exec app
\ bundle_report compatibility --rails-version=5.0.7 => Incompatible with Rails 5.0.7 (with new versions that are compatible): These gems will need to be upgraded before upgrading to Rails 5.0.7. rails-dom-testing 1.0.9 - upgrade to 2.0.3 test_after_commit 1.2.2 - new version, 1.2.2, is not compatible with Rails 5.0.7 2 gems incompatible with Rails 5.0.7 -
@etagwerker | #RailsUpgrades | https://fastruby.io/upgrade 72 Exercise #4: next bundle
install Time: 15 minutes https://fastruby.io/upgrade#7 -
@etagwerker | #RailsUpgrades | https://fastruby.io/upgrade Now that you can next
bundle install successfully... 75 -
@etagwerker | #RailsUpgrades | https://fastruby.io/upgrade 76 $ docker-compose exec app
\ next rspec spec/models -
@etagwerker | #RailsUpgrades | https://fastruby.io/upgrade 78 $ docker-compose exec app
\ next rspec spec/models rake aborted! Bundler::GemRequireError: There was an error while trying to load the gem 'test_after_commit'. Gem Load Error is: after_commit testing is baked into rails 5, you no longer need test_after_commit gem Backtrace for gem load error is: /Users/etagwerker/.rvm/gems/ruby-2.4.5@petitions/gems/ test_after_commit-1.1.0/lib/test_after_commit.rb:4:in `<top (required)>' /Users/etagwerker/.rvm/rubies/ruby-2.4.5/lib/ruby/site_ruby/2.4.0/ bundler/runtime.rb:81:in `require' /Users/etagwerker/.rvm/rubies/ruby-2.4.5/lib/ruby/site_ruby/2.4.0/ bundler/runtime.rb:81:in `block (2 levels) in require' /Users/etagwerker/.rvm/rubies/ruby-2.4.5/lib/ruby/site_ruby/2.4.0/ bundler/runtime.rb:76:in `each' -
@etagwerker | #RailsUpgrades | https://fastruby.io/upgrade 79 # Gemfile group :test
do # ... gem 'test_after_commit' unless next? end -
@etagwerker | #RailsUpgrades | https://fastruby.io/upgrade # spec/support/after_commits.rb if defined?(TestAfterCommit) TestAfterCommit.enabled
= false RSpec.configure do |config| config.around(:each) do |example| # ... end end end -
@etagwerker | #RailsUpgrades | https://fastruby.io/upgrade 81 $ docker-compose exec app
\ next rspec spec/models NoMethodError: undefined method `hide_action' for Delayed::Web::ApplicationController:Class # ./config/initializers/delayed_web.rb:10:in `block in <top (required)>' # ./config/initializers/delayed_web.rb:7:in `class_eval' # ./config/initializers/delayed_web.rb:7:in `<top (required)>' # /Users/etagwerker/.rvm/gems/ruby-2.4.5@petitions/gems/ activesupport-5.0.7.2/lib/active_support/dependencies.rb:287:in `load' # /Users/etagwerker/.rvm/gems/ruby-2.4.5@petitions/gems/ activesupport-5.0.7.2/lib/active_support/dependencies.rb:287:in `block in load' # /Users/etagwerker/.rvm/gems/ruby-2.4.5@petitions/gems/ activesupport-5.0.7.2/lib/active_support/dependencies.rb:259:in `load_dependency' -
@etagwerker | #RailsUpgrades | https://fastruby.io/upgrade 82 # config/initializers/delayed_web.rb Delayed::Web::ApplicationController.class_eval do
include Authentication, FlashI18n hide_action :admin_request? def admin_request? true end protected def admin_login_url main_app.admin_login_url end end -
@etagwerker | #RailsUpgrades | https://fastruby.io/upgrade 83 # config/initializers/delayed_web.rb Delayed::Web::ApplicationController.class_eval do
include Authentication, FlashI18n protected def admin_request? true end def admin_login_url main_app.admin_login_url end end -
@etagwerker | #RailsUpgrades | https://fastruby.io/upgrade 86 $ docker-compose exec app
\ next rspec spec/models DEPRECATION WARNING: ActiveRecord::Base.raise_in_transactional_callbacks= is deprecated, has no effect and will be removed without replacement. (called from <top (required)> at /usr/src/app/ config/environment.rb:5) DEPRECATION WARNING: #table_exists? currently checks both tables and views. This behavior is deprecated and will be changed with Rails 5.1 to only check tables. Use #data_source_exists? instead. (called from table_exists? at / usr/src/app/app/models/site.rb:23) DEPRECATION WARNING: Passing an argument to force an association to reload is now deprecated and will be removed in Rails 5.1. Please call `reload_rejection` instead. (called from rejection at /usr/src/app/app/models/petition.rb:639) ... -
@etagwerker | #RailsUpgrades | https://fastruby.io/upgrade 88 Exercise #5: next rspec
spec/models Time: 20 minutes https://fastruby.io/upgrade#8 -
@etagwerker | #RailsUpgrades | https://fastruby.io/upgrade 91 $ docker-compose exec app
\ next rspec spec/lib DEPRECATION WARNING: `config.serve_static_files` is deprecated and will be removed in Rails 5.1. Please use `config.public_file_server.enabled = true` instead. (called from block in <top (required)> at /usr/src/app/config/environments/ test.rb:16) DEPRECATION WARNING: `config.static_cache_control` is deprecated and will be removed in Rails 5.1. Please use `config.public_file_server.headers = { 'Cache-Control' => 'public, max- age=3600' }` instead. (called from block in <top (required)> at /usr/src/app/config/environments/ test.rb:17) -
@etagwerker | #RailsUpgrades | https://fastruby.io/upgrade 92 Exercise #6: next rspec
spec/lib Time: 10 minutes https://fastruby.io/upgrade#9 -
@etagwerker | #RailsUpgrades | https://fastruby.io/upgrade 95 $ docker-compose exec app
\ next rspec spec/controllers DEPRECATION WARNING: Using positional arguments in functional tests has been deprecated, in favor of keyword arguments, and will be removed in Rails 5.1. Deprecated style: get :show, { id: 1 }, nil, { notice: "This is a flash message" } New keyword style: get :show, params: { id: 1 }, flash: { notice: "This is a flash message" }, session: nil # Can safely be omitted. (called from block (4 levels) in <top (required)> at /usr/src/app/spec/ controllers/admin/petition_tags_controller_spec.rb:46) DEPRECATION WARNING: Using positional arguments in functional tests has been deprecated, in favor of keyword arguments, and will be removed in Rails 5.1. -
@etagwerker | #RailsUpgrades | https://fastruby.io/upgrade # Gemfile group :development, :test
do gem 'next_rails', '~> 1.0.1' # … gem 'rubocop' gem 'rubocop-rails' end -
@etagwerker | #RailsUpgrades | https://fastruby.io/upgrade 97 $ docker-compose down $
docker-compose up --build -d $ docker-compose exec app \ ./bin/docker-setup -
@etagwerker | #RailsUpgrades | https://fastruby.io/upgrade 98 $ docker-compose exec app
\ rubocop \ --only Rails/HttpPositionalArguments \ --require rubocop-rails --auto-correct spec/controllers -
@etagwerker | #RailsUpgrades | https://fastruby.io/upgrade 99 $ docker-compose exec app
\ next rspec spec/controllers -
@etagwerker | #RailsUpgrades | https://fastruby.io/upgrade 100 Exercise #7: next rspec
spec/controllers Time: 15 minutes https://fastruby.io/upgrade#10 -
@etagwerker | #RailsUpgrades | https://fastruby.io/upgrade Unofficial Guides 103 1.https://fastruby.io/blog/rails/upgrades/upgrade-to-rails-3.html 2.https://fastruby.io/blog/rails/upgrades/upgrade-to-rails-3-1.html
3.https://fastruby.io/blog/rails/upgrades/upgrade-to-rails-3-2.html 4.https://fastruby.io/blog/rails/upgrades/upgrade-rails-from-3-2-to-4-0.html 5.https://fastruby.io/blog/rails/upgrades/upgrade-rails-from-4-0-to-4-1.html 6.https://fastruby.io/blog/rails/upgrades/upgrade-rails-from-4-1-to-4-2.html 7.https://fastruby.io/blog/rails/upgrades/active-record-5-1-api-changes.html 8.https://fastruby.io/blog/rails/upgrades/upgrade-rails-from-4-2-to-5-0.html 9.https://fastruby.io/blog/rails/upgrades/upgrade-rails-from-5-0-to-5-1.html 10.https://fastruby.io/blog/rails/upgrades/upgrade-rails-from-5-1-to-5-2.html 11.https://fastruby.io/blog/rails/upgrades/upgrade-rails-from-5-2-to-6-0.html -
@etagwerker | #RailsUpgrades | https://fastruby.io/upgrade ... ✅ 2.3 3.0 ✅
3.0 3.1 ✅ 3.1 3.2 ✅ 3.2 4.0 ✅ 4.0 4.1 ✅ 4.1 4.2 ✅ 4.2 5.0 ✅ 5.0 5.1 ✅ 5.1 5.2 ✅ 5.2 6.0 108 Gemfile Gemfile.next { } -
@etagwerker | #RailsUpgrades | https://fastruby.io/upgrade For every version jump: bundle
install bundle exec rake Smoke test 109 -
@etagwerker | #RailsUpgrades | https://fastruby.io/upgrade # config/environments/test.rb Rails.application.configure do #
... # Raise on deprecation notices config.active_support.deprecation = :raise # ... end 119 -
@etagwerker | #RailsUpgrades | https://fastruby.io/upgrade # Rakefile # ... task
default: %i[ bundle:audit brakeman:check spec spec:javascripts cucumber ] 121 -
@etagwerker | #RailsUpgrades | https://fastruby.io/upgrade namespace :bundle do desc "Audit
bundle for any known vulnerabilities" task :audit do unless system "bundle-audit check --update" exit 1 end end end 122 -
@etagwerker | #RailsUpgrades | https://fastruby.io/upgrade 124 # Gemfile source 'https://rubygems.org'
git_source(:github) do |repo_name| repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/") "https://github.com/#{repo_name}.git" end if next? gem 'rails', github: 'rails/rails' else gem 'rails', '~> 6.0.0.rc2' end -
@etagwerker | #RailsUpgrades | https://fastruby.io/upgrade Resources 127 1.https://github.com/clio/ten_years_rails 2.https://github.com/alphagov/e-petitions 3.https://github.com/rubyperu/ready4rails
4.https://edgeguides.rubyonrails.org/upgrading_ruby_on_rails.html#the-upgrade-process 5.https://fastruby.io/blog/tags/upgrades 6.https://semver.org 7.https://github.com/Shopify/bootboot 8.https://github.com/fastruby/rails_upgrader 9.http://railsdiff.org 10.https://github.com/hintmedia/moderate_parameters 11.https://edgeguides.rubyonrails.org/upgrading_ruby_on_rails.html#the-update-task