summaryrefslogtreecommitdiff
path: root/doc/development/code_review.md
blob: 02f187d62c85d9eb589b52e3b754d3de0c37935a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
---
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/product/ux/technical-writing/#assignments
---

# Code Review Guidelines

This guide contains advice and best practices for performing code review, and
having your code reviewed.

All merge requests for GitLab CE and EE, whether written by a GitLab team member
or a wider community member, must go through a code review process to ensure the
code is effective, understandable, maintainable, and secure.

## Getting your merge request reviewed, approved, and merged

Before you begin:

- Familiarize yourself with the [contribution acceptance criteria](contributing/merge_request_workflow.md#contribution-acceptance-criteria).
- If you need some guidance (for example, if it's your first merge request), feel free to ask
  one of the [Merge request coaches](https://about.gitlab.com/company/team/?department=merge-request-coach).

As soon as you have code to review, have the code **reviewed** by a [reviewer](https://about.gitlab.com/handbook/engineering/workflow/code-review/#reviewer).
This reviewer can be from your group or team, or a [domain expert](#domain-experts).
The reviewer can:

- Give you a second opinion on the chosen solution and implementation.
- Help look for bugs, logic problems, or uncovered edge cases.

If the merge request is trivial to review (for example, fixing a typo or a tiny refactor that doesn't change the behavior or any data),
you can skip the reviewer step and directly ask a [maintainer](https://about.gitlab.com/handbook/engineering/workflow/code-review/#maintainer).
Otherwise, a merge request should always be first reviewed by a reviewer in each
[category (e.g. backend, database)](#approval-guidelines)
the MR touches, as maintainers may not have the relevant domain knowledge, and
also to spread the workload.

For assistance with security scans or comments, include the Application Security Team (`@gitlab-com/gl-security/appsec`).

The reviewers use the [reviewer functionality](../user/project/merge_requests/reviews/index.md) in the sidebar.
Reviewers can add their approval by [approving additionally](../user/project/merge_requests/approvals/index.md#approve-a-merge-request).

Depending on the areas your merge request touches, it must be **approved** by one
or more [maintainers](https://about.gitlab.com/handbook/engineering/workflow/code-review/#maintainer).
The **Approved** button is in the merge request widget.

Getting your merge request **merged** also requires a maintainer. If it requires
more than one approval, the last maintainer to review and approve merges it.

Read more about [author responsibilities](#the-responsibility-of-the-merge-request-author) below.

### Domain experts

Domain experts are team members who have substantial experience with a specific technology,
product feature, or area of the codebase. Team members are encouraged to self-identify as
domain experts and add it to their
[team profiles](https://about.gitlab.com/handbook/engineering/workflow/code-review/#how-to-self-identify-as-a-domain-expert).

When self-identifying as a domain expert, it is recommended to assign the MR changing the `.yml` file to be merged by an already established Domain Expert or a corresponding Engineering Manager.

We make the following assumption with regards to automatically being considered a domain expert:

- Team members working in a specific stage/group (for example, create: source code) are considered domain experts for that area of the app they work on.
- Team members working on a specific feature (for example, search) are considered domain experts for that feature.

We default to assigning reviews to team members with domain expertise for code reviews. For UX reviews we default to the recommended designer from the Reviewer roulette.
When a suitable [domain expert](#domain-experts) isn't available, you can choose any team member to review the MR, or follow the [Reviewer roulette](#reviewer-roulette) recommendation (see above for UX reviews).

To find a domain expert:

- In the Merge Request approvals widget, select [View eligible approvers](../user/project/merge_requests/approvals/rules.md#eligible-approvers).
  This widget shows recommended and required approvals per area of the codebase.
  These rules are defined in [Code Owners](../user/project/merge_requests/approvals/rules.md#code-owners-as-eligible-approvers).
- View the list of team members who work in the [stage or group](https://about.gitlab.com/handbook/product/categories/#devops-stages) related to the merge request.
- View team members' domain expertise on the [engineering projects](https://about.gitlab.com/handbook/engineering/projects/) page or on the [GitLab team page](https://about.gitlab.com/company/team/). Domains are self-identified, so use your judgment to map the changes on your merge request to a domain.
- Look for team members who have contributed to the files in the merge request. View the logs by running `git log <file>`.
- Look for team members who have reviewed the files. You can find the relevant merge request by:
  1. Getting the commit SHA by using `git log <file>`.
  1. Navigating to `https://gitlab.com/gitlab-org/gitlab/-/commit/<SHA>`.
  1. Selecting the related merge request shown for the commit.

### Reviewer roulette

NOTE:
Reviewer roulette is an internal tool for use on GitLab.com, and not available for use on customer installations.

The [Danger bot](dangerbot.md) randomly picks a reviewer and a maintainer for
each area of the codebase that your merge request seems to touch. It makes
**recommendations** for developer reviewers and you should override it if you think someone else is a better
fit. User-facing changes are also required to have a UX review, even if it's behind a feature flag. Default to the recommended UX reviewer suggested.

It picks reviewers and maintainers from the list at the
[engineering projects](https://about.gitlab.com/handbook/engineering/projects/)
page, with these behaviors:

- It doesn't pick people whose Slack or [GitLab status](../user/profile/index.md#set-your-current-status):
  - Contains the string `OOO`, `PTO`, `Parental Leave`, or `Friends and Family`.
  - GitLab user **Busy** indicator is set to `True`.
  - Emoji is from one of these categories:
    - **On leave** - 🌴 `:palm_tree:`, 🏖️ `:beach:`, ⛱ `:beach_umbrella:`, 🏖 `:beach_with_umbrella:`, 🌞 `:sun_with_face:`, 🎡 `:ferris_wheel:`
    - **Out sick** - 🌡️ `:thermometer:`, 🤒 `:face_with_thermometer:`
    - **At capacity** - 🔴 `:red_circle:`
    - **Focus mode** - 💡 `:bulb:` (focusing on their team's work)
- It doesn't pick people who are already assigned a number of reviews that is equal to
  or greater than their chosen "review limit". The review limit is the maximum number of
  reviews people are ready to handle at a time. Set a review limit by using one of the following
  as a Slack or [GitLab status](../user/profile/index.md#set-your-current-status):
  - 0️⃣ - `:zero:` (similar to `:red_circle:`)
  - 1️⃣ - `:one:`
  - 2️⃣ - `:two:`
  - 3️⃣ - `:three:`
  - 4️⃣ - `:four:`
  - 5️⃣ - `:five:`

  Review requests for merge requests that do not target the default branch of any
  project under the [security group](https://gitlab.com/gitlab-org/security/) are
  not counted. These MRs are usually backports, and maintainers or reviewers usually
  do not need much time reviewing them.

- Team members whose Slack or [GitLab status](../user/profile/index.md#set-your-current-status) emoji
  is 🔵 `:large_blue_circle:` are more likely to be picked. This applies to both reviewers and trainee maintainers.
  - Reviewers with 🔵 `:large_blue_circle:` are two times as likely to be picked as other reviewers.
  - [Trainee maintainers](https://about.gitlab.com/handbook/engineering/workflow/code-review/#trainee-maintainer) with 🔵 `:large_blue_circle:` are three times as likely to be picked as other reviewers.
- People whose [GitLab status](../user/profile/index.md#set-your-current-status) emoji
  is 🔶 `:large_orange_diamond:` or 🔸 `:small_orange_diamond:` are half as likely to be picked.
- It always picks the same reviewers and maintainers for the same
  branch name (unless their out-of-office (`OOO`) status changes, as in point 1). It
  removes leading `ce-` and `ee-`, and trailing `-ce` and `-ee`, so
  that it can be stable for backport branches.
- People whose Slack or [GitLab status](../user/profile/index.md#set-your-current-status) emoji
  is Ⓜ `:m:`are only suggested as reviewers on projects they are a maintainer of.

The [Roulette dashboard](https://gitlab-org.gitlab.io/gitlab-roulette/) contains:

- Assignment events in the last 7 and 30 days.
- Currently assigned merge requests per person.
- Sorting by different criteria.
- A manual reviewer roulette.
- Local time information.

For more information, review [the roulette README](https://gitlab.com/gitlab-org/gitlab-roulette).

As an experiment, we want to introduce a `local` reviewer status for database reviews. Local reviewers are reviewers
focusing on work from a team/stage, but not outside of it. This helps to focus and build great domain
knowledge. We are not introducing changes to the reviewer roulette till we evaluate the impact and feedback from this
experiment. We ask to respect reviewers who decline reviews based on their focus on `local` reviews. For tracking purposes,
please use in your personal YAML file entry: `- reviewer database local` instead of `- reviewer database`.

### Approval guidelines

As described in the section on the responsibility of the maintainer below, you
are recommended to get your merge request approved and merged by maintainers
with [domain expertise](#domain-experts).

| If your merge request includes  | It must be approved by a |
| ------------------------------- | ------------------------ |
| `~backend` changes (*1*)        | [Backend maintainer](https://about.gitlab.com/handbook/engineering/projects/#gitlab_maintainers_backend). |
| `~database` migrations or changes to expensive queries (*2*) | [Database maintainer](https://about.gitlab.com/handbook/engineering/projects/#gitlab_maintainers_database). Refer to the [database review guidelines](database_review.md) for more details. |
| `~workhorse` changes | [Workhorse maintainer](https://about.gitlab.com/handbook/engineering/projects/#gitlab_maintainers_workhorse). |
| `~frontend` changes (*1*)       | [Frontend maintainer](https://about.gitlab.com/handbook/engineering/projects/#gitlab_maintainers_frontend). |
| `~UX` user-facing changes (*3*) | [Product Designer](https://about.gitlab.com/handbook/engineering/projects/#gitlab_reviewers_UX). Refer to the [design and user interface guidelines](contributing/design.md) for details. |
| Adding a new JavaScript library (*1*) | - [Frontend foundations member](https://about.gitlab.com/direction/manage/foundations/) if the library significantly increases the [bundle size](https://gitlab.com/gitlab-org/frontend/playground/webpack-memory-metrics/-/blob/master/doc/report.md).<br/>- A [legal department member](https://about.gitlab.com/handbook/legal/) if the license used by the new library hasn't been approved for use in GitLab.<br/><br/>More information about license compatibility can be found in our [GitLab Licensing and Compatibility documentation](licensing.md). |
| A new dependency or a file system change | - [Distribution team member](https://about.gitlab.com/company/team/). See how to work with the [Distribution team](https://about.gitlab.com/handbook/engineering/development/enablement/systems/distribution/#how-to-work-with-distribution) for more details.<br/>- For RubyGems, request an [AppSec review](gemfile.md#request-an-appsec-review). |
| `~documentation` or `~UI text` changes | [Technical writer](https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments) based on assignments in the appropriate [DevOps stage group](https://about.gitlab.com/handbook/product/categories/#devops-stages). |
| Changes to development guidelines | Follow the [review process](development_processes.md#development-guidelines-review) and get the approvals accordingly. |
| End-to-end **and** non-end-to-end changes (*4*) | [Software Engineer in Test](https://about.gitlab.com/handbook/engineering/quality/#individual-contributors). |
| Only End-to-end changes (*4*) **or** if the MR author is a [Software Engineer in Test](https://about.gitlab.com/handbook/engineering/quality/#individual-contributors) | [Quality maintainer](https://about.gitlab.com/handbook/engineering/projects/#gitlab_maintainers_qa). |
| A new or updated [application limit](https://about.gitlab.com/handbook/product/product-processes/#introducing-application-limits) | [Product manager](https://about.gitlab.com/company/team/). |
| Analytics Instrumentation (telemetry or analytics) changes | [Analytics Instrumentation engineer](https://gitlab.com/gitlab-org/analytics-section/product-intelligence/engineers). |
| An addition of, or changes to a [Feature spec](testing_guide/testing_levels.md#frontend-feature-tests) | [Quality maintainer](https://about.gitlab.com/handbook/engineering/projects/#gitlab_maintainers_qa) or [Quality reviewer](https://about.gitlab.com/handbook/engineering/projects/#gitlab_reviewers_qa). |
| A new service to GitLab (Puma, Sidekiq, Gitaly are examples) | [Product manager](https://about.gitlab.com/company/team/). See the [process for adding a service component to GitLab](adding_service_component.md) for details. |
| Changes related to authentication or authorization | [Manage:Authentication and Authorization team member](https://about.gitlab.com/company/team/). Check the [code review section on the group page](https://about.gitlab.com/handbook/engineering/development/dev/manage/authentication-and-authorization/#additional-considerations) for more details. Patterns for files known to require review from the team are listed in the in the `Authentication and Authorization` section of the [`CODEOWNERS`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/CODEOWNERS) file, and the team will be listed in the approvers section of all merge requests that modify these files. |

- (*1*): Specs other than JavaScript specs are considered `~backend` code. Haml markup is considered `~frontend` code. However, Ruby code within Haml templates is considered `~backend` code. When in doubt, request both a frontend and backend review.
- (*2*): We encourage you to seek guidance from a database maintainer if your merge
  request is potentially introducing expensive queries. It is most efficient to comment
  on the line of code in question with the SQL queries so they can give their advice.
- (*3*): User-facing changes include both visual changes (regardless of how minor),
  and changes to the rendered DOM which impact how a screen reader may announce
  the content.
- (*4*): End-to-end changes include all files within the `qa` directory.

#### Acceptance checklist

This checklist encourages the authors, reviewers, and maintainers of merge requests (MRs) to confirm changes were analyzed for high-impact risks to quality, performance, reliability, security, observability, and maintainability.

Using checklists improves quality in software engineering. This checklist is a straightforward tool to support and bolster the skills of contributors to the GitLab codebase.

##### Quality

See the [test engineering process](https://about.gitlab.com/handbook/engineering/quality/quality-engineering/test-engineering/) for further quality guidelines.

1. You have self-reviewed this MR per [code review guidelines](code_review.md).
1. For the code that this change impacts, you believe that the automated tests ([Testing Guide](testing_guide/index.md)) validate functionality that is highly important to users (including consideration of [all test levels](testing_guide/testing_levels.md)).
1. If the existing automated tests do not cover the above functionality, you have added the necessary additional tests or added an issue to describe the automation testing gap and linked it to this MR.
1. You have considered the technical aspects of this change's impact on GitLab.com hosted customers and self-managed customers.
1. You have considered the impact of this change on the frontend, backend, and database portions of the system where appropriate and applied the `~ux`, `~frontend`, `~backend`, and `~database` labels accordingly.
1. You have tested this MR in [all supported browsers](../install/requirements.md#supported-web-browsers), or determined that this testing is not needed.
1. You have confirmed that this change is [backwards compatible across updates](multi_version_compatibility.md), or you have decided that this does not apply.
1. You have properly separated EE content from FOSS, or this MR is FOSS only.
    - [Where should EE code go?](ee_features.md)
1. You have considered that existing data may be surprisingly varied. For example, a new model validation can break existing records. Consider making validation on existing data optional rather than required if you haven't confirmed that existing data will pass validation.
1. If a test passes with warnings and the failed job includes the text `Flaky test '<path/to/test>' was found in the list of files changed by this MR.`, you have fixed this test, or provided evidence explaining why this flaky test can be ignored.

##### Performance, reliability, and availability

1. You are confident that this MR does not harm performance, or you have asked a reviewer to help assess the performance impact. ([Merge request performance guidelines](merge_request_concepts/performance.md))
1. You have added [information for database reviewers in the MR description](database_review.md#required), or you have decided that it is unnecessary.
    - [Does this MR have database-related changes?](database_review.md)
1. You have considered the availability and reliability risks of this change.
1. You have considered the scalability risk based on future predicted growth.
1. You have considered the performance, reliability, and availability impacts of this change on large customers who may have significantly more data than the average customer.

##### Observability instrumentation

1. You have included enough instrumentation to facilitate debugging and proactive performance improvements through observability.
   See [example](https://gitlab.com/gitlab-org/gitlab/-/issues/346124#expectations) of adding feature flags, logging, and instrumentation.

##### Documentation

1. You have included changelog trailers, or you have decided that they are not needed.
    - [Does this MR need a changelog?](changelog.md#what-warrants-a-changelog-entry)
1. You have added/updated documentation or decided that documentation changes are unnecessary for this MR.
    - [Is documentation required?](https://about.gitlab.com/handbook/product/ux/technical-writing/workflow/#when-documentation-is-required)

##### Security

1. You have confirmed that if this MR contains changes to processing or storing of credentials or tokens, authorization, and authentication methods, or other items described in [the security review guidelines](https://about.gitlab.com/handbook/security/#when-to-request-a-security-review), you have added the `~security` label and you have `@`-mentioned `@gitlab-com/gl-security/appsec`.
1. You have reviewed the documentation regarding [internal application security reviews](https://about.gitlab.com/handbook/security/#internal-application-security-reviews) for **when** and **how** to request a security review and requested a security review if this is warranted for this change.
1. If there are security scan results that are blocking the MR (due to the [scan result policies](https://gitlab.com/gitlab-com/gl-security/security-policies)):
    - For true positive findings, they should be corrected before the merge request is merged. This will remove the AppSec approval required by the scan result policy.
    - For false positive findings, something that should be discussed for risk acceptance, or anything questionable, please ping `@gitlab-com/gl-security/appsec`.

##### Deployment

1. You have considered using a feature flag for this change because the change may be high risk.
1. If you are using a feature flag, you plan to test the change in staging before you test it in production, and you have considered rolling it out to a subset of production customers before rolling it out to all customers.
    - [When to use a feature flag](https://about.gitlab.com/handbook/product-development-flow/feature-flag-lifecycle/#when-to-use-feature-flags)
1. You have informed the Infrastructure department of a default setting or new setting change per [definition of done](contributing/merge_request_workflow.md#definition-of-done), or decided that this is unnecessary.

##### Compliance

1. You have confirmed that the correct [MR type label](labels/index.md) has been applied.

### The responsibility of the merge request author

The responsibility to find the best solution and implement it lies with the
merge request author. The author or [directly responsible individual](https://about.gitlab.com/handbook/people-group/directly-responsible-individuals/)
(DRI) stays assigned to the merge request as the assignee throughout
the code review lifecycle. If you are unable to set yourself as an assignee, ask a [reviewer](https://about.gitlab.com/handbook/engineering/workflow/code-review/#reviewer) to do this for you.

Before requesting a review from a maintainer to approve and merge, they
should be confident that:

- It actually solves the problem it was meant to solve.
- It does so in the most appropriate way.
- It satisfies all requirements.
- There are no remaining bugs, logical problems, uncovered edge cases,
  or known vulnerabilities.

The best way to do this, and to avoid unnecessary back-and-forth with reviewers,
is to perform a self-review of your own merge request, following the
[Code Review](#reviewing-a-merge-request) guidelines. During this self-review,
try to include comments in the MR on lines
where decisions or trade-offs were made, or where a contextual explanation might aid the reviewer in more easily understanding the code.

To reach the required level of confidence in their solution, an author is expected
to involve other people in the investigation and implementation processes as
appropriate.

They are encouraged to reach out to [domain experts](#domain-experts) to discuss different solutions
or get an implementation reviewed, to product managers and UX designers to clear
up confusion or verify that the end result matches what they had in mind, to
database specialists to get input on the data model or specific queries, or to
any other developer to get an in-depth review of the solution.

If your merge request touches more than one domain (for example, Dynamic Analysis and GraphQL), ask for reviews from an expert from each domain.

If an author is unsure if a merge request needs a [domain expert's](#domain-experts) opinion,
then that indicates it does. Without it, it's unlikely they have the required level of confidence in their
solution.

Before the review, the author is requested to submit comments on the merge
request diff alerting the reviewer to anything important as well as for anything
that demands further explanation or attention. Examples of content that may
warrant a comment could be:

- The addition of a linting rule (RuboCop, JS etc).
- The addition of a library (Ruby gem, JS lib etc).
- Where not obvious, a link to the parent class or method.
- Any benchmarking performed to complement the change.
- Potentially insecure code.

If there are any projects, snippets, or other assets that are required for a reviewer to validate the solution, ensure they have access to those assets before requesting review.

When assigning reviewers, it can be helpful to:

- Add a comment to the MR indicating which *type* of review you are looking for
  from that reviewer.
  - For example, if an MR changes a database query and updates
    backend code, the MR author first needs a `~backend` review and a `~database`
    review. While assigning the reviewers, the author adds a comment to the MR
    letting each reviewer know which domain they should review.
  - Many GitLab team members are domain experts in more than one area,
    so without this type of comment it is sometimes ambiguous what type
    of review they are being asked to provide.
  - Explicitness around MR review types is efficient for the MR author because
    they receive the type of review that they are looking for and it is
    efficient for the MR reviewers because they immediately know which type of review to provide.
  - [Example 1](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75921#note_758161716)
  - [Example 2](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/109500#note_1253955051)

Avoid:

- Adding TODO comments (referenced above) directly to the source code unless the reviewer requires
  you to do so. If TODO comments are added due to an actionable task,
  [include a link to the relevant issue](code_comments.md).
- Adding comments which only explain what the code is doing. If non-TODO comments are added, they should
  [_explain why, not what_](https://blog.codinghorror.com/code-tells-you-how-comments-tell-you-why/).
- Requesting maintainer reviews of merge requests with failed tests. If the tests are failing and you have to request a review, ensure you leave a comment with an explanation.
- Excessively mentioning maintainers through email or Slack (if the maintainer is reachable
through Slack). If you can't add a reviewer for a merge request, `@` mentioning a maintainer in a comment is acceptable and in all other cases adding a reviewer is sufficient.

This saves reviewers time and helps authors catch mistakes earlier.

### The responsibility of the reviewer

Reviewers are responsible for reviewing the specifics of the chosen solution.

[Review the merge request](#reviewing-a-merge-request) thoroughly.

Verify that the merge request meets all [contribution acceptance criteria](contributing/merge_request_workflow.md#contribution-acceptance-criteria).

Some merge requests may require domain experts to help with the specifics.
Reviewers, if they are not a domain expert in the area, can do any of the following:

- Review the merge request and loop in a domain expert for another review. This expert
  can either be another reviewer or a maintainer.
- Pass the review to another reviewer they deem more suitable.
- If no domain experts are available, review on a best-effort basis.

You should guide the author towards splitting the merge request into smaller merge requests if it is:

- Too large.
- Fixes more than one issue.
- Implements more than one feature.
- Has a high complexity resulting in additional risk.

The author may choose to request that the current maintainers and reviewers review the split MRs
or request a new group of maintainers and reviewers.

When you are confident
that it meets all requirements, you should:

- Select **Approve**.
- `@` mention the author to generate a to-do notification, and advise them that their merge request has been reviewed and approved.
- Request a review from a maintainer. Default to requests for a maintainer with [domain expertise](#domain-experts),
however, if one isn't available or you think the merge request doesn't need a review by a [domain expert](#domain-experts), feel free to follow the [Reviewer roulette](#reviewer-roulette) suggestion.
- Remove yourself as a reviewer.

### The responsibility of the maintainer

Maintainers are responsible for the overall health, quality, and consistency of
the GitLab codebase, across domains and product areas.

Consequently, their reviews focus primarily on things like overall
architecture, code organization, separation of concerns, tests, DRYness,
consistency, and readability.

Because a maintainer's job only depends on their knowledge of the overall GitLab
codebase, and not that of any specific domain, they can review, approve, and merge
merge requests from any team and in any product area.

Maintainers are the DRI of assuring that the acceptance criteria of a merge request are reasonably met.
In general, [quality is everyone’s responsibility](https://about.gitlab.com/handbook/engineering/quality/),
but maintainers of an MR are held responsible for **ensuring** that an MR meets those general quality standards.

If a maintainer feels that an MR is substantial enough, or requires a [domain expert](#domain-experts),
maintainers have the discretion to request a review from another reviewer, or maintainer. Here are some
examples of maintainers proactively doing this during review:

- <https://gitlab.com/gitlab-org/gitlab/-/merge_requests/82708#note_872325561>
- <https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38003#note_387981596>
- <https://gitlab.com/gitlab-org/gitlab/-/merge_requests/14017#note_178828088>

Maintainers do their best to also review the specifics of the chosen solution
before merging, but as they are not necessarily [domain experts](#domain-experts), they may be poorly
placed to do so without an unreasonable investment of time. In those cases, they
defer to the judgment of the author and earlier reviewers, in favor of focusing on their primary responsibilities.

If a developer who happens to also be a maintainer was involved in a merge request
as a reviewer, it is recommended that they are not also picked as the maintainer to ultimately approve and merge it.

Maintainers should check before merging if the merge request is approved by the
required approvers. If still awaiting further approvals from others, remove yourself as a reviewer then `@` mention the author and explain why in a comment. Stay as reviewer if you're merging the code.

Certain merge requests may target a stable branch. For an overview of how to handle these requests,
see the [patch release runbook](https://gitlab.com/gitlab-org/release/docs/-/blob/master/general/patch/engineers.md).

After merging, a maintainer should stay as the reviewer listed on the merge request.

### Dogfooding the Reviewers feature

On March 18th 2021, an updated process was put in place aimed at efficiently and consistently dogfooding the Reviewers feature.

Here is a summary of the changes, also reflected in this section above.

- Merge request authors and DRIs stay as Assignees
- Authors request a review from Reviewers when they are expected to review
- Reviewers remove themselves after they're done reviewing/approving
- The last approver stays as Reviewer upon merging

## Best practices

### Everyone

- Be kind.
- Accept that many programming decisions are opinions. Discuss tradeoffs, which
  you prefer, and reach a resolution quickly.
- Ask questions; don't make demands. ("What do you think about naming this
  `:user_id`?")
- Ask for clarification. ("I didn't understand. Can you clarify?")
- Avoid selective ownership of code. ("mine", "not mine", "yours")
- Avoid using terms that could be seen as referring to personal traits. ("dumb",
  "stupid"). Assume everyone is intelligent and well-meaning.
- Be explicit. Remember people don't always understand your intentions online.
- Be humble. ("I'm not sure - let's look it up.")
- Don't use hyperbole. ("always", "never", "endlessly", "nothing")
- Be careful about the use of sarcasm. Everything we do is public; what seems
  like good-natured ribbing to you and a long-time colleague might come off as
  mean and unwelcoming to a person new to the project.
- Consider one-on-one chats or video calls if there are too many "I didn't
  understand" or "Alternative solution:" comments. Post a follow-up comment
  summarizing one-on-one discussion.
- If you ask a question to a specific person, always start the comment by
  mentioning them; this ensures they see it if their notification level is
  set to "mentioned" and other people understand they don't have to respond.

### Having your merge request reviewed

Please keep in mind that code review is a process that can take multiple
iterations, and reviewers may spot things later that they may not have seen the
first time.

- The first reviewer of your code is _you_. Before you perform that first push
  of your shiny new branch, read through the entire diff. Does it make sense?
  Did you include something unrelated to the overall purpose of the changes? Did
  you forget to remove any debugging code?
- Write a detailed description as outlined in the [merge request guidelines](contributing/merge_request_workflow.md#merge-request-guidelines-for-contributors).
  Some reviewers may not be familiar with the product feature or area of the
  codebase. Thorough descriptions help all reviewers understand your request
  and test effectively.
- If you know your change depends on another being merged first, note it in the
  description and set a [merge request dependency](../user/project/merge_requests/dependencies.md).
- Be grateful for the reviewer's suggestions. ("Good call. I'll make that change.")
- Don't take it personally. The review is of the code, not of you.
- Explain why the code exists. ("It's like that because of these reasons. Would
  it be more clear if I rename this class/file/method/variable?")
- Extract unrelated changes and refactorings into future merge requests/issues.
- Seek to understand the reviewer's perspective.
- Try to respond to every comment.
- The merge request author resolves only the threads they have fully
  addressed. If there's an open reply, an open thread, a suggestion,
  a question, or anything else, the thread should be left to be resolved
  by the reviewer.
- It should not be assumed that all feedback requires their recommended changes
  to be incorporated into the MR before it is merged. It is a judgment call by
  the MR author and the reviewer as to if this is required, or if a follow-up
  issue should be created to address the feedback in the future after the MR in
  question is merged.
- Push commits based on earlier rounds of feedback as isolated commits to the
  branch. Do not squash until the branch is ready to merge. Reviewers should be
  able to read individual updates based on their earlier feedback.
- Request a new review from the reviewer once you are ready for another round of
  review. If you do not have the ability to request a review, `@`
  mention the reviewer instead.

### Requesting a review

When you are ready to have your merge request reviewed,
you should [request an initial review](../user/project/merge_requests/reviews/index.md) by selecting a reviewer based on the [approval guidelines](#approval-guidelines).

When a merge request has multiple areas for review, it is recommended you specify which area a reviewer should be reviewing, and at which stage (first or second).
This will help team members who qualify as a reviewer for multiple areas to know which area they're being requested to review.
For example, when a merge request has both `backend` and `frontend` concerns, you can mention the reviewer in this manner:
`@john_doe can you please review ~backend?` or `@jane_doe - could you please give this MR a ~frontend maintainer review?`

You can also use `workflow::ready for review` label. That means that your merge request is ready to be reviewed and any reviewer can pick it. It is recommended to use that label only if there isn't time pressure and make sure the merge request is assigned to a reviewer.

When your merge request receives an approval from the first reviewer it can be passed to a maintainer. You should default to choosing a maintainer with [domain expertise](#domain-experts), and otherwise follow the Reviewer Roulette recommendation or use the label `ready for merge`.

Sometimes, a maintainer may not be available for review. They could be out of the office or [at capacity](https://about.gitlab.com/handbook/engineering/workflow/code-review/#review-response-slo).
You can and should check the maintainer's availability in their profile. If the maintainer recommended by
the roulette is not available, choose someone else from that list.

It is the responsibility of the author for the merge request to be reviewed. If it stays in the `ready for review` state too long it is recommended to request a review from a specific reviewer.

### Volunteering to review

GitLab engineers who have capacity can regularly check the list of [merge requests to review](https://gitlab.com/groups/gitlab-org/-/merge_requests?state=opened&label_name%5B%5D=workflow%3A%3Aready%20for%20review) and add themselves as a reviewer for any merge request they want to review.

### Reviewing a merge request

Understand why the change is necessary (fixes a bug, improves the user
experience, refactors the existing code). Then:

- Try to be thorough in your reviews to reduce the number of iterations.
- Communicate which ideas you feel strongly about and those you don't.
- Identify ways to simplify the code while still solving the problem.
- Offer alternative implementations, but assume the author already considered
  them. ("What do you think about using a custom validator here?")
- Seek to understand the author's perspective.
- Check out the branch, and test the changes locally. You can decide how much manual testing you want to perform.
  Your testing might result in opportunities to add automated tests.
- If you don't understand a piece of code, _say so_. There's a good chance
  someone else would be confused by it as well.
- Ensure the author is clear on what is required from them to address/resolve the suggestion.
  - Consider using the [Conventional Comment format](https://conventionalcomments.org#format) to
    convey your intent.
  - For non-mandatory suggestions, decorate with (non-blocking) so the author knows they can
    optionally resolve within the merge request or follow-up at a later stage.
  - There's a [Chrome/Firefox add-on](https://gitlab.com/conventionalcomments/conventional-comments-button) which you can use to apply [Conventional Comment](https://conventionalcomments.org/) prefixes.
- Ensure there are no open dependencies. Check [linked issues](../user/project/issues/related_issues.md) for blockers. Clarify with the authors
if necessary. If blocked by one or more open MRs, set an [MR dependency](../user/project/merge_requests/dependencies.md).
- After a round of line notes, it can be helpful to post a summary note such as
  "Looks good to me", or "Just a couple things to address."
- Let the author know if changes are required following your review.

WARNING:
**If the merge request is from a fork, also check the [additional guidelines for community contributions](#community-contributions).**

### Merging a merge request

Before taking the decision to merge:

- Set the milestone.
- Confirm that the correct [MR type label](labels/index.md#type-labels) is applied.
- Consider warnings and errors from danger bot, code quality, and other reports.
  Unless a strong case can be made for the violation, these should be resolved
  before merging. A comment must be posted if the MR is merged with any failed job.
- If the MR contains both Quality and non-Quality-related changes, the MR should be merged by the relevant maintainer for user-facing changes (backend, frontend, or database) after the Quality related changes are approved by a Software Engineer in Test.

At least one maintainer must approve an MR before it can be merged. MR authors and
people who add commits to an MR are not authorized to approve or merge the MR and
must seek a maintainer who has not contributed to the MR to approve and merge it.

This policy is in place to satisfy the CHG-04 control of the GitLab
[Change Management Controls](https://about.gitlab.com/handbook/security/change-management-policy.html).

<!-- Or should it link to: https://about.gitlab.com/handbook/engineering/infrastructure/change-management/ ? -->

To implement this policy in `gitlab-org/gitlab`, we have enabled the following
settings to ensure MRs get an approval from a top-level CODEOWNERS maintainer:

- [Prevent approval by author](../user/project/merge_requests/approvals/settings.md#prevent-approval-by-author).
- [Prevent approvals by users who add commits](../user/project/merge_requests/approvals/settings.md#prevent-approvals-by-users-who-add-commits).
- [Prevent editing approval rules in merge requests](../user/project/merge_requests/approvals/settings.md#prevent-editing-approval-rules-in-merge-requests).
- [Remove all approvals when commits are added to the source branch](../user/project/merge_requests/approvals/settings.md#remove-all-approvals-when-commits-are-added-to-the-source-branch)

To update the code owners in the `CODEOWNERS` file for `gitlab-org/gitlab`, follow
the process explained in the [code owners approvals handbook section](https://about.gitlab.com/handbook/engineering/workflow/code-review/#code-owner-approvals).

  There are scenarios such as rebasing locally or applying suggestions that are considered
  the same as adding a commit and could reset existing approvals. Approvals are not removed
  when rebasing from the UI or with the [`/rebase` quick action](../user/project/quick_actions.md).

When ready to merge:

WARNING:
**If the merge request is from a fork, also check the [additional guidelines for community contributions](#community-contributions).**

- Consider using the [Squash and merge](../user/project/merge_requests/squash_and_merge.md#squash-and-merge)
  feature when the merge request has a lot of commits.
  When merging code, a maintainer should only use the squash feature if the
  author has already set this option, or if the merge request clearly contains a
  messy commit history, it will be more efficient to squash commits instead of
  circling back with the author about that. Otherwise, if the MR only has a few commits, we'll
  be respecting the author's setting by not squashing them.
- Go to the merge request's **Pipelines** tab, and select **Run pipeline**. Then, on the **Overview** tab, enable **Auto-merge**.
  Note that:
  - If **[the default branch is broken](https://about.gitlab.com/handbook/engineering/workflow/#broken-master),
    do not merge the merge request** except for
    [very specific cases](https://about.gitlab.com/handbook/engineering/workflow/#criteria-for-merging-during-broken-master).
    For other cases, follow these [handbook instructions](https://about.gitlab.com/handbook/engineering/workflow/#merging-during-broken-master).
  - If the latest pipeline was created before the merge request was approved, start a new pipeline to ensure that full RSpec suite has been run. You may skip this step only if the merge request does not contain any backend change.
  - If the **latest [merged results pipeline](../ci/pipelines/merged_results_pipelines.md)** was **created less than 6 hours ago**, and **finished less than 2 hours ago**, you
    may merge without starting a new pipeline as the merge request is close
    enough to `main`.
- When you set the MR to auto-merge, you should take over
  subsequent revisions for anything that would be spotted after that.
- For merge requests that have had [Squash and merge](../user/project/merge_requests/squash_and_merge.md#squash-and-merge) set,
  the squashed commit's default commit message is taken from the merge request title.
  You're encouraged to [select a commit with a more informative commit message](../user/project/merge_requests/squash_and_merge.md) before merging.

Thanks to **merged results pipelines**, authors no longer have to rebase their
branch as frequently anymore (only when there are conflicts) because the Merge
Results Pipeline already incorporate the latest changes from `main`.
This results in faster review/merge cycles because maintainers don't have to ask
for a final rebase: instead, they only have to start a MR pipeline and set auto-merge.
This step brings us very close to the actual Merge Trains feature by testing the
Merge Results against the latest `main` at the time of the pipeline creation.

### Community contributions

WARNING:
**Review all changes thoroughly for malicious code before starting a
[merged results pipeline](../ci/pipelines/merge_request_pipelines.md#run-pipelines-in-the-parent-project).**

When reviewing merge requests added by wider community contributors:

- Pay particular attention to new dependencies and dependency updates, such as Ruby gems and Node packages.
  While changes to files like `Gemfile.lock` or `yarn.lock` might appear trivial, they could lead to the
  fetching of malicious packages.
- Review links and images, especially in documentation MRs.
- When in doubt, ask someone from `@gitlab-com/gl-security/appsec` to review the merge request **before manually starting any merge request pipeline**.
- Only set the milestone when the merge request is likely to be included in
  the current milestone. This is to avoid confusion around when it'll be
  merged and avoid moving milestone too often when it's not yet ready.

If the MR source branch is more than 1,000 commits behind the target branch:

- Ask the author to rebase it, or consider taking a bias-for-action and rebasing it yourself
  if the MR has "Allows commits from members who can merge to the target branch" enabled.
- Reviewing MRs in the context of recent changes can help prevent hidden runtime conflicts and
  promote consistency. Depending on the nature of the change, you might also want to rebase if the
  MR is less than 1,000 commits behind.
- A forced push could throw off the contributor, so it's a good idea to communicate that you've performed a rebase,
  or check with the contributor first when they're actively working on the MR.
- The rebase can usually be done inside GitLab with the `/rebase` [quick action](../user/project/quick_actions.md).

#### Taking over a community merge request

When an MR needs further changes but the author is not responding for a long period of time,
or is unable to finish the MR, GitLab can take it over in accordance with our
[Closing policy for issues and merge requests](contributing/index.md#closing-policy-for-issues-and-merge-requests).
A GitLab engineer (generally the merge request coach) will:

1. Add a comment to their MR saying you'll take it over to be able to get it merged.
1. Add the label `~"coach will finish"` to their MR.
1. Create a new feature branch from the main branch.
1. Merge their branch into your new feature branch.
1. Open a new merge request to merge your feature branch into the main branch.
1. Link the community MR from your MR and label it as `~"Community contribution"`.
1. Make any necessary final adjustments and ping the contributor to give them the chance to review your changes, and to make them aware that their content is being merged into the main branch.
1. Make sure the content complies with all the merge request guidelines.
1. Follow the regular review process as we do for any merge request.

### The right balance

One of the most difficult things during code review is finding the right
balance in how deep the reviewer can interfere with the code created by a
author.

- Learning how to find the right balance takes time; that is why we have
  reviewers that become maintainers after some time spent on reviewing merge
  requests.
- Finding bugs is important, but thinking about good design is important as
  well. Building abstractions and good design is what makes it possible to hide
  complexity and makes future changes easier.
- Enforcing and improving [code style](contributing/style_guides.md) should be primarily done through
  [automation](https://about.gitlab.com/handbook/values/#cleanup-over-sign-off)
  instead of review comments.
- Asking the author to change the design sometimes means the complete rewrite
  of the contributed code. It's usually a good idea to ask another maintainer or
  reviewer before doing it, but have the courage to do it when you believe it is
  important.
- In the interest of [Iteration](https://about.gitlab.com/handbook/values/#iteration),
  if your review suggestions are non-blocking changes, or personal preference
  (not a documented or agreed requirement), consider approving the merge request
  before passing it back to the author. This allows them to implement your suggestions
  if they agree, or allows them to pass it onto the
  maintainer for review straight away. This can help reduce our overall time-to-merge.
- There is a difference in doing things right and doing things right now.
  Ideally, we should do the former, but in the real world we need the latter as
  well. A good example is a security fix which should be released as soon as
  possible. Asking the author to do the major refactoring in the merge
  request that is an urgent fix should be avoided.
- Doing things well today is usually better than doing something perfectly
  tomorrow. Shipping a kludge today is usually worse than doing something well
  tomorrow. When you are not able to find the right balance, ask other people
  about their opinion.

### GitLab-specific concerns

GitLab is used in a lot of places. Many users use
our [Omnibus packages](https://about.gitlab.com/install/), but some use
the [Docker images](../install/docker.md), some are
[installed from source](../install/installation.md),
and there are other installation methods available. GitLab.com itself is a large
Enterprise Edition instance. This has some implications:

1. **Query changes** should be tested to ensure that they don't result in worse
   performance at the scale of GitLab.com:
   1. Generating large quantities of data locally can help.
   1. Asking for query plans from GitLab.com is the most reliable way to validate
      these.
1. **Database migrations** must be:
   1. Reversible.
   1. Performant at the scale of GitLab.com - ask a maintainer to test the
      migration on the staging environment if you aren't sure.
   1. Categorized correctly:
      - Regular migrations run before the new code is running on the instance.
      - [Post-deployment migrations](database/post_deployment_migrations.md) run _after_
        the new code is deployed, when the instance is configured to do that.
      - [Batched background migrations](database/batched_background_migrations.md) run in Sidekiq, and
        should be used for migrations that
        [exceed the post-deployment migration time limit](migration_style_guide.md#how-long-a-migration-should-take)
        GitLab.com scale.
1. **Sidekiq workers** [cannot change in a backwards-incompatible way](sidekiq/compatibility_across_updates.md):
   1. Sidekiq queues are not drained before a deploy happens, so there are
      workers in the queue from the previous version of GitLab.
   1. If you need to change a method signature, try to do so across two releases,
      and accept both the old and new arguments in the first of those.
   1. Similarly, if you need to remove a worker, stop it from being scheduled in
      one release, then remove it in the next. This allows existing jobs to
      execute.
   1. Don't forget, not every instance is upgraded to every intermediate version
      (some people may go from X.1.0 to X.10.0, or even try bigger upgrades!), so
      try to be liberal in accepting the old format if it is cheap to do so.
1. **Cached values** may persist across releases. If you are changing the type a
   cached value returns (say, from a string or nil to an array), change the
   cache key at the same time.
1. **Settings** should be added as a
   [last resort](https://about.gitlab.com/handbook/product/product-principles/#convention-over-configuration). See [Adding a new setting to GitLab Rails](architecture.md#adding-a-new-setting-in-gitlab-rails).
1. **File system access** is not possible in a [cloud-native architecture](architecture.md#adapting-existing-and-introducing-new-components).
   Ensure that we support object storage for any file storage we need to perform. For more
   information, see the [uploads documentation](uploads/index.md).

### Customer critical merge requests

A merge request may benefit from being considered a customer critical priority because there is a significant benefit to the business in doing so.

Properties of customer critical merge requests:

- The [VP of Development](https://about.gitlab.com/job-families/engineering/development/management/vp/) ([@clefelhocz1](https://gitlab.com/clefelhocz1)) is the DRI for deciding if a merge request qualifies as customer critical.
- The DRI applies the `customer-critical-merge-request` label to the merge request.
- It is required that the reviewers and maintainers involved with a customer critical merge request are engaged as soon as this decision is made.
- It is required to prioritize work for those involved on a customer critical merge request so that they have the time available necessary to focus on it.
- It is required to adhere to GitLab [values](https://about.gitlab.com/handbook/values/) and processes when working on customer critical merge requests, taking particular note of family and friends first/work second, definition of done, iteration, and release when it's ready.
- Customer critical merge requests are required to not reduce security, introduce data-loss risk, reduce availability, nor break existing functionality per the process for [prioritizing technical decisions](https://about.gitlab.com/handbook/engineering/development/principles/#prioritizing-technical-decisions).
- On customer critical requests, it is _recommended_ that those involved _consider_ coordinating synchronously (Zoom, Slack) in addition to asynchronously (merge requests comments) if they believe this may reduce the elapsed time to merge even though this _may_ sacrifice [efficiency](https://about.gitlab.com/company/culture/all-remote/asynchronous/#evaluating-efficiency.md).
- After a customer critical merge request is merged, a retrospective must be completed with the intention of reducing the frequency of future customer critical merge requests.

## Examples

How code reviews are conducted can surprise new contributors. Here are some examples of code reviews that should help to orient you as to what to expect.

**["Modify `DiffNote` to reuse it for Designs"](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/13703):**
It contained everything from nitpicks around newlines to reasoning
about what versions for designs are, how we should compare them
if there was no previous version of a certain file (parent vs.
blank `sha` vs empty tree).

**["Support multi-line suggestions"](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/25211)**:
The MR itself consists of a collaboration between FE and BE,
and documenting comments from the author for the reviewer.
There's some nitpicks, some questions for information, and
towards the end, a security vulnerability.

**["Allow multiple repositories per project"](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/10251)**:
ZJ referred to the other projects (workhorse) this might impact,
suggested some improvements for consistency. And James' comments
helped us with overall code quality (using delegation, `&.` those
types of things), and making the code more robust.

**["Support multiple assignees for merge requests"](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/10161)**:
A good example of collaboration on an MR touching multiple parts of the codebase. Nick pointed out interesting edge cases, James Lopez also joined in raising concerns on import/export feature.

### Credits

Largely based on the [`thoughtbot` code review guide](https://github.com/thoughtbot/guides/tree/master/code-review).