Add Rails update guidelines

This commit is contained in:
Dmitry Gruzd 2021-10-06 18:53:25 +00:00
parent e44c0183df
commit 30e6846e2b
3 changed files with 150 additions and 0 deletions

View file

@ -190,6 +190,7 @@ the [reviewer values](https://about.gitlab.com/handbook/engineering/workflow/rev
- [Issuable-like Rails models](issuable-like-models.md)
- [Issue types vs first-class types](issue_types.md)
- [DeclarativePolicy framework](policies.md)
- [Rails update guidelines](rails_update.md)
### Debugging

View file

@ -0,0 +1,110 @@
---
stage: none
group: unassigned
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
# Rails update guidelines
We strive to run GitLab using the latest Rails releases to benefit from performance, security updates, and new features.
## Rails update approach
1. [Prepare an MR for GitLab](#prepare-an-mr-for-gitlab).
1. [Prepare an MR for Gitaly](#prepare-an-mr-for-gitaly).
1. [Create patch releases and backports for security patches](#create-patch-releases-and-backports-for-security-patches).
### Prepare an MR for GitLab
1. Check the [Upgrading Ruby on Rails](https://guides.rubyonrails.org/upgrading_ruby_on_rails.html) guide and prepare the application for the upcoming changes.
1. Update the `rails` gem version in `Gemfile`.
1. Run `bundle update rails`.
1. Run the update task `rake rails:update`.
1. Update the `activesupport` version in `qa/Gemfile`.
1. Run `bundle update --conservative activesupport` in the `qa` folder.
1. Resolve any Bundler conflicts.
1. Ensure that `@rails/ujs` and `@rails/actioncable` npm packages match the new rails version in [`package.json`](https://gitlab.com/gitlab-org/gitlab/blob/master/package.json).
1. Create an MR with the `pipeline:run-all-rspec` label and see if pipeline breaks.
1. To resolve and debug spec failures use `git bisect` against the rails repository. See the [debugging section](#git-bisect-against-rails) below.
1. 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](https://my.diffend.io/gems/activerecord/6.1.3.2/6.1.4.1).
### Prepare an MR for Gitaly
1. Update the `activesupport` gem version in [Gitaly Ruby's Gemfile](https://gitlab.com/gitlab-org/gitaly/-/blob/master/ruby/Gemfile).
1. Run `bundle update --conservative activesupport`.
1. Create an MR against the Gitaly project with these changes.
1. Make this MR dependent on the MR created in the GitLab project.
1. Merged this MR only **after** merging the GitLab project's MR.
### Create patch releases and backports for security patches
If the Rails update 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](https://about.gitlab.com/community/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`](https://git-scm.com/docs/git-bisect) command against the Rails repository:
1. Clone the `rails` project in a folder of your choice. For example, it might be the GDK root dir:
```shell
cd <GDK_FOLDER>
git clone https://github.com/rails/rails.git
```
1. Replace the `gem 'rails'` line in GitLab `Gemfile` with:
```ruby
gem 'rails', ENV['RAILS_VERSION'], path: ENV['RAILS_FOLDER']
```
1. Set the `RAILS_FOLDER` env variable with the folder you cloned Rails into:
```shell
export RAILS_FOLDER="<GDK_FOLDER>/rails"
```
1. Change the directory to `RAILS_FOLDER` and set the range for the `git bisect` command:
```shell
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.
1. Start the `git bisect` process and pass spec's file name(s) to `scripts/rails-update-bisect` as an argument or arguments. It can be faster to pick only one example instead of an entire spec file.
```shell
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
```
1. When the process is completed, `git bisect` prints the commit hash, which you can use to find the corresponding MR in the [`rails/rails`](https://github.com/rails/rails) repository.
1. Execute `git bisect reset` to exit the `bisect` mode.
1. Revert the changes to `Gemfile`:
```shell
git checkout -- Gemfile
```
### Follow-up reading material
- [Upgrading Ruby on Rails guide](https://guides.rubyonrails.org/upgrading_ruby_on_rails.html)
- [Rails releases page](https://github.com/rails/rails/releases)

39
scripts/rails-update-bisect Executable file
View file

@ -0,0 +1,39 @@
#!/bin/bash
SCRIPT_DIR="$( cd "$( dirname "$0" )" && pwd )"
GITLAB_DIR="$(dirname "$SCRIPT_DIR")"
# Because this script is intended to be run with `git bisect run`,
# we are returning `-1` status code to alert `git bisect` of failures.
#
# See: https://git-scm.com/docs/git-bisect#_bisect_run
#
abort_bisect () {
exit -1
}
if [ $# -eq 0 ]; then
echo "No arguments supplied. Please provide spec file(s) as first argument(s)"
abort_bisect
fi
[[ -z "${RAILS_FOLDER}" ]] && { echo >&2 "RAILS_FOLDER env variable is not set"; abort_bisect; }
if ! grep -q -E "gem 'rails'.+RAILS_VERSION.+RAILS_FOLDER" $GITLAB_DIR/Gemfile; then
echo "Gemfile is not modified"
echo "Please alter the gem 'rails' line in Gemfile with:"
echo "gem 'rails', ENV['RAILS_VERSION'], path: ENV['RAILS_FOLDER']"
abort_bisect
fi
export RAILS_VERSION=$(cat $RAILS_FOLDER/RAILS_VERSION)
cd $GITLAB_DIR && \
echo "Updating dependencies... this could take a while." && \
bundle update rails --quiet
test $? -eq 0 || { echo >&2 "bundle update has failed"; abort_bisect; }
# Stop spring if it's installed
command -v spring >/dev/null 2>&1 && spring stop
bin/rspec $@