UPGRADINGTO RAILS 3Changing the wheels on the bus at 80mph(or 128.784 kph for everyone else)Andrew Bloomgarden Julian Giuca
Andrew introductionAndrew Bloomgarden@aughr2
Julian Giuca@juliangiuca3
Julian Giuca@juliangiuca3
Julian Giuca@juliangiuca3
Julian Giuca@juliangiuca3
4
Overview5You can dual bootRails 2 and Rails 3
Do try this at home!6
Let’s talk about numbers...7
Rails versions in the wild2.x.x 3.x.x8Numberofaccounts
2.2.2# 2.2.3# 2.3.2# 2.3.4# 2.3.5# 2.3.8# 2.3.10# 2.3.11# 2.3.12# 2.3.14# 2.3.15# 3.0.1# 3.0.3# 3.0.5# 3.0.11# 3.0.15# 3.0...
Rails version vs number of server10
Upgrading to Rails 31. Procrastinate2. Goals3. Feature Branch4. Fix tests5. Merge6. Push7. Cross fingers8. Fix Production11
Putting it offRearchitecting the app firstDo it all in a big spike!Have a ruby_19 branchSTUPID THINGS WE TRIED12
Rails 3? Why now?13
Rails 3? Why now?Someone will make upgradingeasier soon!13
Rails 3? Why now?Someone will make upgradingeasier soon!Oh man, this is going tobe awful.13
Gems are leaving us behind14
Gems are leaving us behind14
Come and work onour Rails 2.3 app!15
16
Upgrading to Rails 31. Procrastinate2. Goals3. Feature Branch4. Fix tests5. Merge6. Push7. Cross fingers8. Fix Production17
A bit of history18
A bit of historyMove to Rails 2.0.118
A bit of history18
A bit of historyRails 2.3.1470,000 application LOC59,000 test LOC18
Don’t break the world19
Keep everyone happynot thisthisthisthis20
Keep ourselves happyCONFLICT (content): …CONFLICT (content): …CONFLICT (content): …⋮CONFLICT (content): …Automatic merge f...
Upgrading to Rails 31. Procrastinate2. Goals3. Feature Branch4. Fix tests5. Merge6. Push7. Cross fingers8. Fix Production22
23
24
I’m looking at you Rails 1.2.2 people25
I’m looking at you Rails 1.2.2 people25
Gemfileplatforms :ruby_18 dogem ruby-debugendplatforms :ruby_19 dogem debuggerend26
27
Monkey patched!27
In the Gemfileif ENV.include?("USE_RAILS_3")class Bundler::Dslif !self.method_defined?(:to_definition_without_rails3_lockfi...
Two Gemfile.lock files29
Gemfileif is_rails3gem rails, 3.0.19gem lighthouse-api, ~>2.0.0gem dalli, ~> 2.3.0gem jquery-rails, ~>2.1gem active_reloade...
# Booting in Rails 3 mode$ export USE_RAILS_3=true$ bundle install$ rails server31
Upgrading to Rails 31. Procrastinate2. Goals3. Feature Branch4. Fix tests5. Merge6. Push7. Cross fingers8. Fix Production32
Upgrading to Rails 31. Procrastinate2. Goals3. Feature Branch4. Fix tests5. Merge6. Push7. Cross fingers8. Fix ProductionIm...
From an idea to production1. Procrastinate2. Goals3. Onto master4. Getting it to work5. Rollout6. Lessons learned33
From an idea to production1. Procrastinate2. Goals3. Onto master4. Getting it to work5. Rollout6. Lessons learned34
Make it easy for everyone# Rails 2$ script/server# Rails 3$ script/server335
From an idea to production1. Procrastinate2. Goals3. Onto master4. Getting it to work5. Rollout6. Lessons learned36
Onto master1. Boot Rails 32. Dual boot3. Unbreak Rails 24. Merge upstream37
Unbreak Rails 2BootsRails2RunsRails2BootsRails3RunsRails3Rails 2
Unbreak Rails 2BootsRails2RunsRails2BootsRails3RunsRails3Rails 2Boot Rails 3
Unbreak Rails 2BootsRails2RunsRails2BootsRails3RunsRails3Rails 2Boot Rails 3
Unbreak Rails 2BootsRails2RunsRails2BootsRails3RunsRails3Rails 2Boot Rails 3
Unbreak Rails 2BootsRails2RunsRails2BootsRails3RunsRails3Rails 2Boot Rails 3Dual boot
Unbreak Rails 2BootsRails2RunsRails2BootsRails3RunsRails3Rails 2Boot Rails 3Dual boot
Unbreak Rails 2BootsRails2RunsRails2BootsRails3RunsRails3Rails 2Boot Rails 3Dual boot
Unbreak Rails 2BootsRails2RunsRails2BootsRails3RunsRails3Rails 2Boot Rails 3Dual bootRestore Rails 2
Unbreak Rails 2BootsRails2RunsRails2BootsRails3RunsRails3Rails 2Boot Rails 3Dual bootRestore Rails 2
Onto master1. Boot Rails 32. Dual boot3. Unbreak Rails 24. Merge upstream39
From an idea to production1. Procrastinate2. Goals3. Onto master4. Getting it to work5. Rollout6. Lessons learned40
Dual-booting that worksRails 2.3 Rails 3config/boot.rb requires Rails requires Bundlerconfig/environment.rbloads, configures,...
Dual-booting that worksRails 2.3 Rails 3config/boot.rb requires Rails requires Bundlerconfig/environment.rbloads, configures,...
Just make it work42
config/boot.rbif ENV.include?("USE_RAILS_3")require rubygems# Set up gems listed in the Gemfile.ENV[BUNDLE_GEMFILE] ||=File...
config/boot.rbif ENV.include?("USE_RAILS_3")require rubygems# Set up gems listed in the Gemfile.ENV[BUNDLE_GEMFILE] ||=File...
config/boot.rbif ENV.include?("USE_RAILS_3")require rubygems# Set up gems listed in the Gemfile.ENV[BUNDLE_GEMFILE] ||=File...
config/environment.rb# Load the rails applicationrequire_relative "application"if CoreAppConfig.is_rails3?# Initialize the ...
config/application.rbmodule NewRelicApplicationConfigdef self.rails3_config(config)# Do Rails 3 stuffcommon_config(config)e...
config/application.rb46if is_rails3require rails/allBundler.require(:default, Rails.env)module RpmSiteclass Application < R...
config/application.rb46if is_rails3require rails/allBundler.require(:default, Rails.env)module RpmSiteclass Application < R...
config/application.rb46if is_rails3require rails/allBundler.require(:default, Rails.env)module RpmSiteclass Application < R...
Have tests you trust47
Use CI48
Upgrade dependencies on master49
BackgroundJob to ResqueBj.submit script/background/do_something.rb,:email => DEV_TEAM50
Never againdef getopts opts = {}if RUBY_VERSION.to_f >= 1.9# In 1.9 this throw/catch/getopts nonsense breakslambda do |*ar...
Add an abstraction layerBj.submit script/background/do_something.rb,:email => DEV_TEAM52
Add an abstraction layerAsync::Command.new(script/background/do_something.rb).notify(DEV_TEAM).enqueue52
Use Resque or BackgroundJobclass Async::Command < Async::Jobif CoreAppConfig.use_resque?include Async::ResqueJobextend Res...
Finally, use Resque54
Branch by abstraction55The problem being with featurebranches is that the current state ofany one of them might be unable ...
Branch by abstraction55Branch by abstraction: a patternfor making large-scale changes to yourapplication incrementally on ...
Punt when you can56
ActiveSupport::Deprecation.silenced = true57
Your old routes still workRpmSite::Application.routes.draw do |map|Jammit::Routes.draw(map)# ...end58
Your old routes still workRpmSite::Application.routes.draw do |map|Jammit::Routes.draw(map)# ...end58
Your old mailers still workclass AccountMailer < ApplicationMailerdef new_account(account, user, subscription)headers[Erro...
Your old mailers still workclass AccountMailer < ApplicationMailerdef new_account(account, user, subscription)headers[Erro...
Your old models (can) still workself.store_full_sti_class = false60
Your old views (can) still workhelper PrototypeHelperclear_helpers61
Your error handling (can) still work# included into ApplicationControllerdef rescue_with_handler(e)if super # ActiveSuppor...
Temporarily ugly63if CoreAppConfig.is_rails3?# do somethingelse# do something elseend
From an idea to production1. Procrastinate2. Goals3. Onto master4. Getting it to work5. Rollout6. Lessons learned64
We wantYOU to test!65To run in Rails 3, just runscript/server3
Extensive manual testing66DatabaseData collectionUIRails 3 UI
Make everyone a tester67
Turn on Rails 3 by default-is_rails3 = ENV.include?("USE_RAILS_3")+is_rails3 = !ENV.include?("USE_RAILS_2")68
Incompatible sessions69ActionDispatch::Session::SessionRestoreError(Original exception: uninitialized constantActionContro...
Incompatible sessions69
Deploy a canary70
Pause the world71
Deploy all the servers72
Oops73
74
And we’re done!75
And we’re done!75
A few very tiny fires76
Breaking the audit trailActionController::Base.class_eval docache_sweeper :audit_sweeperendAudit.add_observer(AuditSweeper...
Rushed Resque rollout78
Punching ActiveScaffold in the face.../bundle/ruby/1.9.1/gems/active_scaffold-3.0.26/lib/active_scaffold/bridges/date_pick...
Lost BackgroundJob instrumentationThis page left intentionally blank80
Tagging green build off of Rails 2 tests81
Lots of cleanup82
From an idea to production1. Procrastinate2. Goals3. Onto master4. Getting it to work5. Rollout6. Lessons learned83
Lessons learned1. Preorder the donuts your on-call engineers like2. Deprecate ActiveScaffold3. Schedule lots of time for fi...
•Get it into master as early as possible•Incremental everything•CI is your bestest childhood friend(and you secretly have ...
newrelic.com/rails3_upgrade@aughr | @juliangiuca86We’re done (and we’re hiring)
Upcoming SlideShare
Loading in …5
×

Upgrading to Rails 3

1,299 views
1,107 views

Published on

Changing the wheels on the bus at 80 mph
Andrew Bloomgarden and Julian Giuca
RailsConf 2013

Long-running branches are painful, but upgrading to Rails 3 requires one if you can't stop development, right? Wrong! At New Relic, we worked on upgrading to Rails 3 on master while letting development continue in Rails 2. We patched Bundler, built a backwards-compatible boot sequence, and punched ActiveScaffold in the face. Other developers, meanwhile, released 1400 commits worth of work without noticing any changes. We talk about what we did, why we did it, and why we think this approach can help developers get over the hurdle into the Rails 3 promised land.

Published in: Technology, Education
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
1,299
On SlideShare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
0
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Upgrading to Rails 3

  1. 1. UPGRADINGTO RAILS 3Changing the wheels on the bus at 80mph(or 128.784 kph for everyone else)Andrew Bloomgarden Julian Giuca
  2. 2. Andrew introductionAndrew Bloomgarden@aughr2
  3. 3. Julian Giuca@juliangiuca3
  4. 4. Julian Giuca@juliangiuca3
  5. 5. Julian Giuca@juliangiuca3
  6. 6. Julian Giuca@juliangiuca3
  7. 7. 4
  8. 8. Overview5You can dual bootRails 2 and Rails 3
  9. 9. Do try this at home!6
  10. 10. Let’s talk about numbers...7
  11. 11. Rails versions in the wild2.x.x 3.x.x8Numberofaccounts
  12. 12. 2.2.2# 2.2.3# 2.3.2# 2.3.4# 2.3.5# 2.3.8# 2.3.10# 2.3.11# 2.3.12# 2.3.14# 2.3.15# 3.0.1# 3.0.3# 3.0.5# 3.0.11# 3.0.15# 3.0.18# 3.0.19# 3.1.1# 3.2.1# 3.2.8# 3.2.11# 3.2.13#Rails versions with >1 server2.x.x 3.x.xNumberofaccounts
  13. 13. Rails version vs number of server10
  14. 14. Upgrading to Rails 31. Procrastinate2. Goals3. Feature Branch4. Fix tests5. Merge6. Push7. Cross fingers8. Fix Production11
  15. 15. Putting it offRearchitecting the app firstDo it all in a big spike!Have a ruby_19 branchSTUPID THINGS WE TRIED12
  16. 16. Rails 3? Why now?13
  17. 17. Rails 3? Why now?Someone will make upgradingeasier soon!13
  18. 18. Rails 3? Why now?Someone will make upgradingeasier soon!Oh man, this is going tobe awful.13
  19. 19. Gems are leaving us behind14
  20. 20. Gems are leaving us behind14
  21. 21. Come and work onour Rails 2.3 app!15
  22. 22. 16
  23. 23. Upgrading to Rails 31. Procrastinate2. Goals3. Feature Branch4. Fix tests5. Merge6. Push7. Cross fingers8. Fix Production17
  24. 24. A bit of history18
  25. 25. A bit of historyMove to Rails 2.0.118
  26. 26. A bit of history18
  27. 27. A bit of historyRails 2.3.1470,000 application LOC59,000 test LOC18
  28. 28. Don’t break the world19
  29. 29. Keep everyone happynot thisthisthisthis20
  30. 30. Keep ourselves happyCONFLICT (content): …CONFLICT (content): …CONFLICT (content): …⋮CONFLICT (content): …Automatic merge failed; fix conflictsand then commit the result.21
  31. 31. Upgrading to Rails 31. Procrastinate2. Goals3. Feature Branch4. Fix tests5. Merge6. Push7. Cross fingers8. Fix Production22
  32. 32. 23
  33. 33. 24
  34. 34. I’m looking at you Rails 1.2.2 people25
  35. 35. I’m looking at you Rails 1.2.2 people25
  36. 36. Gemfileplatforms :ruby_18 dogem ruby-debugendplatforms :ruby_19 dogem debuggerend26
  37. 37. 27
  38. 38. Monkey patched!27
  39. 39. In the Gemfileif ENV.include?("USE_RAILS_3")class Bundler::Dslif !self.method_defined?(:to_definition_without_rails3_lockfile)alias_method :to_definition_without_rails3_lockfile, :to_definitionenddef to_definition(old_lockfile, unlock)current = File.expand_path(Dir.pwd)filename = File.join(current, "Gemfile_rails3.lock")lockfile = Pathname.new(filename)to_definition_without_rails3_lockfile(lockfile, unlock)endendmodule Bundler::SharedHelpersdef default_lockfilecurrent = File.expand_path(Dir.pwd)filename = File.join(current, "Gemfile_rails3.lock")lockfile = Pathname.new(filename)Pathname.new(lockfile)endendend28
  40. 40. Two Gemfile.lock files29
  41. 41. Gemfileif is_rails3gem rails, 3.0.19gem lighthouse-api, ~>2.0.0gem dalli, ~> 2.3.0gem jquery-rails, ~>2.1gem active_reloadelsegem rails, 2.3.15gem lighthouse-api, ~>1.1.0gem dalli, ~> 1.0.4end30
  42. 42. # Booting in Rails 3 mode$ export USE_RAILS_3=true$ bundle install$ rails server31
  43. 43. Upgrading to Rails 31. Procrastinate2. Goals3. Feature Branch4. Fix tests5. Merge6. Push7. Cross fingers8. Fix Production32
  44. 44. Upgrading to Rails 31. Procrastinate2. Goals3. Feature Branch4. Fix tests5. Merge6. Push7. Cross fingers8. Fix ProductionImproved!32
  45. 45. From an idea to production1. Procrastinate2. Goals3. Onto master4. Getting it to work5. Rollout6. Lessons learned33
  46. 46. From an idea to production1. Procrastinate2. Goals3. Onto master4. Getting it to work5. Rollout6. Lessons learned34
  47. 47. Make it easy for everyone# Rails 2$ script/server# Rails 3$ script/server335
  48. 48. From an idea to production1. Procrastinate2. Goals3. Onto master4. Getting it to work5. Rollout6. Lessons learned36
  49. 49. Onto master1. Boot Rails 32. Dual boot3. Unbreak Rails 24. Merge upstream37
  50. 50. Unbreak Rails 2BootsRails2RunsRails2BootsRails3RunsRails3Rails 2
  51. 51. Unbreak Rails 2BootsRails2RunsRails2BootsRails3RunsRails3Rails 2Boot Rails 3
  52. 52. Unbreak Rails 2BootsRails2RunsRails2BootsRails3RunsRails3Rails 2Boot Rails 3
  53. 53. Unbreak Rails 2BootsRails2RunsRails2BootsRails3RunsRails3Rails 2Boot Rails 3
  54. 54. Unbreak Rails 2BootsRails2RunsRails2BootsRails3RunsRails3Rails 2Boot Rails 3Dual boot
  55. 55. Unbreak Rails 2BootsRails2RunsRails2BootsRails3RunsRails3Rails 2Boot Rails 3Dual boot
  56. 56. Unbreak Rails 2BootsRails2RunsRails2BootsRails3RunsRails3Rails 2Boot Rails 3Dual boot
  57. 57. Unbreak Rails 2BootsRails2RunsRails2BootsRails3RunsRails3Rails 2Boot Rails 3Dual bootRestore Rails 2
  58. 58. Unbreak Rails 2BootsRails2RunsRails2BootsRails3RunsRails3Rails 2Boot Rails 3Dual bootRestore Rails 2
  59. 59. Onto master1. Boot Rails 32. Dual boot3. Unbreak Rails 24. Merge upstream39
  60. 60. From an idea to production1. Procrastinate2. Goals3. Onto master4. Getting it to work5. Rollout6. Lessons learned40
  61. 61. Dual-booting that worksRails 2.3 Rails 3config/boot.rb requires Rails requires Bundlerconfig/environment.rbloads, configures,and initializes theappinitializes the appconfig/application.rb doesn’t existloads andconfigures the app41
  62. 62. Dual-booting that worksRails 2.3 Rails 3config/boot.rb requires Rails requires Bundlerconfig/environment.rbloads, configures,and initializes theappinitializes the appconfig/application.rb doesn’t existloads andconfigures the app41
  63. 63. Just make it work42
  64. 64. config/boot.rbif ENV.include?("USE_RAILS_3")require rubygems# Set up gems listed in the Gemfile.ENV[BUNDLE_GEMFILE] ||=File.expand_path(../../Gemfile, __FILE__)require bundler/setup43else# 123 lines that load Rails# All that for this:Rails.boot!end
  65. 65. config/boot.rbif ENV.include?("USE_RAILS_3")require rubygems# Set up gems listed in the Gemfile.ENV[BUNDLE_GEMFILE] ||=File.expand_path(../../Gemfile, __FILE__)require bundler/setup43else# 123 lines that load Rails# All that for this:Rails.boot!end
  66. 66. config/boot.rbif ENV.include?("USE_RAILS_3")require rubygems# Set up gems listed in the Gemfile.ENV[BUNDLE_GEMFILE] ||=File.expand_path(../../Gemfile, __FILE__)require bundler/setup43else# 123 lines that load Rails# All that for this:Rails.boot!end
  67. 67. config/environment.rb# Load the rails applicationrequire_relative "application"if CoreAppConfig.is_rails3?# Initialize the rails applicationRpmSite::Application.initialize!end44
  68. 68. config/application.rbmodule NewRelicApplicationConfigdef self.rails3_config(config)# Do Rails 3 stuffcommon_config(config)enddef self.rails2_config(config)# Do Rails 2 stuffcommon_config(config)enddef self.common_config(config)# ...endend45
  69. 69. config/application.rb46if is_rails3require rails/allBundler.require(:default, Rails.env)module RpmSiteclass Application < Rails::Application::NewRelicApplicationConfig.rails3_config(config)endendelseRails::Initializer.run do |config|::NewRelicApplicationConfig.rails2_config(config)endend
  70. 70. config/application.rb46if is_rails3require rails/allBundler.require(:default, Rails.env)module RpmSiteclass Application < Rails::Application::NewRelicApplicationConfig.rails3_config(config)endendelseRails::Initializer.run do |config|::NewRelicApplicationConfig.rails2_config(config)endend
  71. 71. config/application.rb46if is_rails3require rails/allBundler.require(:default, Rails.env)module RpmSiteclass Application < Rails::Application::NewRelicApplicationConfig.rails3_config(config)endendelseRails::Initializer.run do |config|::NewRelicApplicationConfig.rails2_config(config)endend
  72. 72. Have tests you trust47
  73. 73. Use CI48
  74. 74. Upgrade dependencies on master49
  75. 75. BackgroundJob to ResqueBj.submit script/background/do_something.rb,:email => DEV_TEAM50
  76. 76. Never againdef getopts opts = {}if RUBY_VERSION.to_f >= 1.9# In 1.9 this throw/catch/getopts nonsense breakslambda do |*args|keys, default, ignored = args[keys].flatten.each do |key|[key, key.to_s, key.to_s.intern].each do |key|return opts[key] if opts.has_key?(key)endendreturn defaultendelse # In 1.8 you cant return across threadslambda do |*args|keys, default, ignored = argscatch(opt) do[keys].flatten.each do |key|[key, key.to_s, key.to_s.intern].each do |key|throw opt, opts[key] if opts.has_key?(key)endenddefaultendendendend51
  77. 77. Add an abstraction layerBj.submit script/background/do_something.rb,:email => DEV_TEAM52
  78. 78. Add an abstraction layerAsync::Command.new(script/background/do_something.rb).notify(DEV_TEAM).enqueue52
  79. 79. Use Resque or BackgroundJobclass Async::Command < Async::Jobif CoreAppConfig.use_resque?include Async::ResqueJobextend Resque::Plugins::Historyelseinclude Async::BjJobend# ...end53
  80. 80. Finally, use Resque54
  81. 81. Branch by abstraction55The problem being with featurebranches is that the current state ofany one of them might be unable tobe deployed for a number of weekswhile the team gets it right.Thosebranches just end up running andrunning ….– Paul Hammant
  82. 82. Branch by abstraction55Branch by abstraction: a patternfor making large-scale changes to yourapplication incrementally on mainline.– Jez Humble
  83. 83. Punt when you can56
  84. 84. ActiveSupport::Deprecation.silenced = true57
  85. 85. Your old routes still workRpmSite::Application.routes.draw do |map|Jammit::Routes.draw(map)# ...end58
  86. 86. Your old routes still workRpmSite::Application.routes.draw do |map|Jammit::Routes.draw(map)# ...end58
  87. 87. Your old mailers still workclass AccountMailer < ApplicationMailerdef new_account(account, user, subscription)headers[Errors-to] = BOUNCE_ACCOUNTfrom BILLING_ACCOUNTsubject "New Relic invoice account request"recipients INVOICE_RECIPIENT@account = account@user = user@subscription = subscriptionendend59
  88. 88. Your old mailers still workclass AccountMailer < ApplicationMailerdef new_account(account, user, subscription)headers[Errors-to] = BOUNCE_ACCOUNTfrom BILLING_ACCOUNTsubject "New Relic invoice account request"recipients INVOICE_RECIPIENT@account = account@user = user@subscription = subscriptionendend59
  89. 89. Your old models (can) still workself.store_full_sti_class = false60
  90. 90. Your old views (can) still workhelper PrototypeHelperclear_helpers61
  91. 91. Your error handling (can) still work# included into ApplicationControllerdef rescue_with_handler(e)if super # ActiveSupport::Rescuabletrueelserescue_action_in_public etrueendend62
  92. 92. Temporarily ugly63if CoreAppConfig.is_rails3?# do somethingelse# do something elseend
  93. 93. From an idea to production1. Procrastinate2. Goals3. Onto master4. Getting it to work5. Rollout6. Lessons learned64
  94. 94. We wantYOU to test!65To run in Rails 3, just runscript/server3
  95. 95. Extensive manual testing66DatabaseData collectionUIRails 3 UI
  96. 96. Make everyone a tester67
  97. 97. Turn on Rails 3 by default-is_rails3 = ENV.include?("USE_RAILS_3")+is_rails3 = !ENV.include?("USE_RAILS_2")68
  98. 98. Incompatible sessions69ActionDispatch::Session::SessionRestoreError(Original exception: uninitialized constantActionController::Flash::FlashHash)
  99. 99. Incompatible sessions69
  100. 100. Deploy a canary70
  101. 101. Pause the world71
  102. 102. Deploy all the servers72
  103. 103. Oops73
  104. 104. 74
  105. 105. And we’re done!75
  106. 106. And we’re done!75
  107. 107. A few very tiny fires76
  108. 108. Breaking the audit trailActionController::Base.class_eval docache_sweeper :audit_sweeperendAudit.add_observer(AuditSweeper.instance)class AuditSweeper < ActionController::Caching::Sweeperobserve Auditend77
  109. 109. Rushed Resque rollout78
  110. 110. Punching ActiveScaffold in the face.../bundle/ruby/1.9.1/gems/active_scaffold-3.0.26/lib/active_scaffold/bridges/date_picker/lib/datepicker_bridge.rb:127:in`binread:No such file or directory - .../public/javascripts/active_scaffold/default/date_picker_bridge.js (Errno::ENOENT)79
  111. 111. Lost BackgroundJob instrumentationThis page left intentionally blank80
  112. 112. Tagging green build off of Rails 2 tests81
  113. 113. Lots of cleanup82
  114. 114. From an idea to production1. Procrastinate2. Goals3. Onto master4. Getting it to work5. Rollout6. Lessons learned83
  115. 115. Lessons learned1. Preorder the donuts your on-call engineers like2. Deprecate ActiveScaffold3. Schedule lots of time for firefighting and cleanup84
  116. 116. •Get it into master as early as possible•Incremental everything•CI is your bestest childhood friend(and you secretly have a crush on them)The special magic pony sauce85
  117. 117. newrelic.com/rails3_upgrade@aughr | @juliangiuca86We’re done (and we’re hiring)

×