Rails upgrade guidelines
We strive to run GitLab using the latest Rails releases to benefit from performance, security updates, and new features.
Rails upgrade approach
Prepare an MR for GitLab
- Check the Upgrading Ruby on Rails guide and prepare the application for the upcoming changes.
- Update the
rails
gem version inGemfile
. - Run
bundle update --conservative rails
. - For major and minor version updates, run
bin/rails app:update
and check if any of the suggested changes should be applied. - Update the
activesupport
version inqa/Gemfile
. - Run
bundle update --conservative activesupport
in theqa
folder. - Update the
activerecord_version
version invendor/gems/attr_encrypted/attr_encrypted.gemspec
. - Run
bundle update --conservative activerecord
in thevendor/gems/attr_encrypted
folder. - Resolve any Bundler conflicts.
- Ensure that
@rails/ujs
and@rails/actioncable
npm packages match the new rails version inpackage.json
. - Run
yarn patch-package @rails/ujs
after updating this to ensure our local patch file version matches. - Create an MR with the
pipeline:run-all-rspec
label and see if pipeline breaks. - To resolve and debug spec failures use
git bisect
against the rails repository. See the debugging section below. - Include links to the Gem diffs between the two versions in the merge request description. For example, this is the gem diff for
activesupport
6.1.3.2 to 6.1.4.1.
Prepare an MR for Gitaly
No longer necessary as Gitaly no longer has Ruby code.
Create patch releases and backports for security patches
If the Rails upgrade was over a patch release and it contains important security fixes, make sure to release it in a GitLab patch release to self-managed customers. Consult with our release managers for how to proceed.
Deprecation Logger
We also log Ruby and Rails deprecation warnings into a dedicated log file, log/deprecation_json.log
. It provides
clues when there is code that is not adequately covered by tests and hence would slip past DeprecationToolkitEnv
.
For GitLab SaaS, GitLab team members can inspect these log events in Kibana (https://log.gprd.gitlab.net/goto/f7cebf1ff05038d901ba2c45925c7e01
).
Git bisect against Rails
Usually, if you know which Rails change caused the spec to fail, it adds additional context and
helps to find the fix for the failure.
To efficiently and quickly find which Rails change caused the spec failure you can use the
git bisect
command against the Rails repository:
-
Clone the
rails
project in a folder of your choice. For example, it might be the GDK root dir:cd <GDK_FOLDER> git clone https://github.com/rails/rails.git
-
Replace the
gem 'rails'
line in GitLabGemfile
with:gem 'rails', ENV['RAILS_VERSION'], path: ENV['RAILS_FOLDER']
-
Set the
RAILS_FOLDER
environment variable with the folder you cloned Rails into:export RAILS_FOLDER="<GDK_FOLDER>/rails"
-
Change the directory to
RAILS_FOLDER
and set the range for thegit bisect
command:cd $RAILS_FOLDER git bisect start <NEW_VERSION_TAG> <OLD_VERSION_TAG>
Where
<NEW_VERSION_TAG>
is the tag where the spec is red and<OLD_VERSION_TAG>
is the one with the green spec. For example,git bisect start v6.1.4.1 v6.1.3.2
if we're upgrading from version 6.1.3.2 to 6.1.4.1. Replace<NEW_VERSION_TAG>
with the tag where the spec is red and<OLD_VERSION_TAG>
with the one with the green spec. For example,git bisect start v6.1.4.1 v6.1.3.2
if we're upgrading from version 6.1.3.2 to 6.1.4.1. In the output, you can see how many steps approximately it takes to find the commit. -
Start the
git bisect
process and pass spec's filenames toscripts/rails-update-bisect
as arguments. It can be faster to pick only one example instead of an entire spec file.git bisect run <GDK_FOLDER>/gitlab/scripts/rails-update-bisect spec/models/ability_spec.rb # OR git bisect run <GDK_FOLDER>/gitlab/scripts/rails-update-bisect spec/models/ability_spec.rb:7
-
When the process is completed,
git bisect
prints the commit hash, which you can use to find the corresponding MR in therails/rails
repository. -
Execute
git bisect reset
to exit thebisect
mode. -
Revert the changes to
Gemfile
:git checkout -- Gemfile