Upgrading the Rails version of your application can feel like a daunting task, however, if approached in a logical and ordered manner it can be accomplished with little pain.
Introduction
We’ve carried out a number of major and minor Rails version upgrades on a large Ruby on Rails monolith and have built a process around our experiences that we use to make the upgrade as smooth as possible.
Prerequisites
Our primary prerequisite before starting an upgrade process is that the test suite has sufficient coverage to give us confidence that breaking changes are surfaced. If this confidence is not there, time will need to be committed to creating tests that cover the gaps.
Depending on where your project tests suite is, this could be one of the biggest time commitments in the upgrade process, however, having a robust test suite with good coverage is a must with any application so it’s time well spent.
Our Process
This is our process for upgrading a Ruby on Rails application to a new version of the Rails framework, each step is important and we make sure it is fully covered before moving on to the next. We also only ever move up one Rails version at a time, repeating this process fully if there’s more than one version upgrade required.
At each stage we document and communicate the changes made so the existing development team are fully up to speed on the process, can provide feedback and incorporate any necessary changes to their own feature branches. This ensures that as feature branches get merged they do not introduce deprecated or incompatible code.
Deprecations
Our first step is to tackle any existing deprecation warnings - we like to get these cleared and deployed before anything else is looked at as it’s highly likely any existing deprecation warnings are going to be a roadblock in the Rails version upgrade. This will almost certainly require upgrading your application to the latest patch release of the current Rails version if it’s not already. As part of this step we also evaluate the minimum Ruby version required for the new Rails version, upgrading and deploying where necessary.
Gem Dependencies
Each dependency needs evaluating, typically either only moving to the version that is required for compatibility with the target Rails version or the latest release that supports the current Rails version. We like to spend time examining the gem’s change log to get a clear understanding of the changes made since the version currently deployed. In some cases it’s a simple case of moving to the new version with little or no further action required, in others application code changes may be required and/or require other dependencies to be updated. In rarer cases an updated version of a dependency that works with the new Rails version may not be available - this will either require code changes to be made in the gem itself or an alternative found.
As with backward compatible changes, we approach this one step at a time, with frequent deployments to production to reduce risk and help spot any problems early.
Backwards Compatible Changes
In our experience many of the breaking changes between Ruby, Rails and Gem dependency versions can be addressed prior to a Rails version upgrade. It’s far easier to address these one at a time with the existing Rails version and get the new code deployed and proven in production, significantly reducing the impact area each change makes. The end goal is to reduce the footprint of the final deployment with the new Rails version to the smallest possible size.
Rails Upgrade
Once we’ve got our deprecations resolved, dependencies updated and backward compatible changes made - all tested and deployed to production - we then move to the Rails version update itself. This is another one step at a time process, examining failing tests and changes to the Rails framework that may require code changes, breaking down each into their own unit of work.
To make this process easier to manage we like to use the BootBoot gem from Shopify. This highly useful gem allows you to run and test your app with both the current and new Rails versions and provides a structure to have the code changes required for the new Rails version sit side by side with the old.
Testing
Before rolling out the new Rails version into production we like to make use of a local Docker installation that replicates a production-like environment. This allows for a pre-release sanity check that all tests are passing and offers a production mode walk through of the application via manual UI testing. Nothing hurts more than a broken asset pipeline in production, so it is always good to check things like these beforehand!
An additional step prior to production rollout would be deployment to a hosted staging environment, allowing a QA Team and/or other project stakeholders the ability to test and verify all changes.
Production Rollout
The penultimate stage of our process is the rollout to production. This can either be a full deployment or, making use of the BootBoot gem, a partial rollout. Dual booting the new Rails version with a partial rollout can be useful in containing any potential issues with the new code to a subset of servers and allows for a quick switch back should any issues arise. With the new code running in production we like to closely monitor for any exceptions and performance regressions and only once we’re happy that everything is running as expected, complete the rollout to all servers.
Code Cleanup
Finally, once we’ve fully signed off the production rollout, we can tidy up the code, removing the dual boot logic and any code supporting the prior Rails version making the move to the new Rails version permanent.
Get in touch
Looking for help with your Ruby on Rails upgrade? With over a decade of experience building and maintaining Ruby on Rails applications, we’re confident we’ve travelled down your road before and are available to offer help and assistance at any stage of your development cycle. If you are looking for support with your Ruby on Rails upgrade, whether that’s upgrading to a newer version or right the way through to Rails 7.0, we’re here to help take on that project. Get in touch with us today via our contact form or on hello@circle-sd.com to see how we can help.