This blog post is taking a deeper look at phase 1 of upgrading a large Ruby on Rails up in smallish steps. The focus with these phases is to be able to do a small enough piece and get it merged into the main branch as quickly as possible in order to prevent regression due to new features being added. This has the added benefit of making the upgrade process visible to everyone and making the upgrade a full team effort.
The following is what the details of phase 1 of the upgrade process could look like.
Phase 1: Second Gemfile
Goal: Once this phase is done, it helps ensure that from here onwards no incompatible gems version are updated/added that don’t bundle with both Rails versions.
How: This phase involves getting a second Gemfile.lock that uses the next rails version building correctly on CI. Set up the Gemfile so that it can be used to manage 2 versions of Rails. This is basically achieved by creating a Gemfile-next that evals Gemfile and sets a variable that can be used in the Gemfile to switch between versions. The follow gist https://gist.github.com/grantspeelman/235f4cf83fdc4fab94fc could help with this.
- Create a “Spike/Implement Rails upgrade Gemfile” story and plan according to your process.
- Once you start on the story: Create a branch for it.
- Attempt to Get a working Gemfile-next and Gemfile-next.lock (check https://gist.github.com/grantspeelman/235f4cf83fdc4fab94fc for examples) and add to version control
- cp Gemfile.lock Gemfile-next.lock
- set the rails version inside your Gemfile based on @next_upgrade
- BUNDLE_GEMFILE=Gemfile-next bundle update
- Attempt to resolve version conflict issues and Create new refactor stories as required *
- If you created new refactor stories
- Merge as much as you can into the main branch.
- Mark the main story as attempted/done/finish/etc.
- Plan the new refactor stories according to your process.
- Once new stories are done, start from Step 1 again.
- Add the new Gemfiles to version control.
- Get building and checking of Gemfile-next onto CI and it’s passing (ie basically have `BUNDLE_GEMFILE=Gemfile-next bundle install –deployment` running on CI).
- Share with the team how to maintain the 2 Gemfiles (using `BUNDLE_GEMFILE=Gemfile-next bundle install`)
- Merge the branch into master.
Once merged in, everyone working on the project needs to maintain both Gemfile locks. ie if they add a new or change a gem it has to be bundled twice ( BUNDLE_GEMFILE=Gemfile-next bundle install ).
Resolving version issues and new refactor stories *
When resolving the version issues here are some guidelines on what to do when.
- attempt resolving by making the version requirements more flexible
- ie change `~> 1.1.0` to `~> 1.1` or `>= 1.1.0`
- create a new refactor story to replace/remove the gem if there is no upgrade path for it
- compare Gemfile.lock with Gemfile-next.lock
- check for minor/major gem version updates.
- consult the gem documentation if there are any breaking changes in the gem versions
- create a refactor stories to “update the code to use the later version” or “replace/remove the gem” accordingly
And that is it.