DEV Community

Wen Ping
Wen Ping

Posted on Originally published at anguskit.com

Who reviews this code: use CODEOWNERS to assign reviewers by directory

This article explains how to assign reviewers by directory. After reading it, you can write a CODEOWNERS file that names who owns each path, turn on Enable CODEOWNERS, and have a new pull request add those people as reviewers based on the paths that changed.

CODEOWNERS is a text file in the repository. Each line names a path and the people who own it. AngusGit reads that file when Enable CODEOWNERS is on. A pull request is a request to merge one branch into another. AngusGit calls it a pull request.

The check uses repository xlliu/test-pr-example. This repository already has Require code review and Require approval from all reviewers on (every assigned person must approve before merge). Enable CODEOWNERS is still off. It has two default reviewers, the people fixed in repository settings and added to every new pull request: one display name is Angus and the login is xlliu, and the other is admin.

1. Where the reviewers on this pull request came from

Open pull request #9 is titled docs: 说明空购物车不计算折扣. It merges feature/link-empty-cart into main. The author is Angus. The body contains Closes #4. It changes 1 file: docs/empty-cart-note.md (+3 -0).

The reviewers are Angus and admin. Both are Pending. The merge card says "This pull request is not ready to merge". Under that are "No status checks" and "Reviews are still pending and must be approved before merge", so Merge pull request is gray.

#9: Angus and admin are both pending, and the merge button is unavailable

Those two people come from the default reviewers in repository settings. They were not calculated from file paths. main also has no .github/CODEOWNERS, no CODEOWNERS at the repository root, and no docs/CODEOWNERS.

2. What CODEOWNERS actually does

CODEOWNERS is calculated once, when a pull request is created, and only if the repository has Require code review on. Pushing more commits to the source branch after creation does not add reviewers for the new files.

Assignment does two things, then removes duplicates:

  • It adds the default reviewers from settings.
  • When Enable CODEOWNERS is on, it reads the file on the target branch and adds the people who match the paths in this change.

A person who is already on the default list does not become two review rows if the file names them again. This repository's default list is already xlliu and admin. If the file names only those two, a new pull request after you turn the switch on still has those two reviewers.

What it can do What it cannot do
When a pull request is created, combine the default reviewers with the people matched by path After the pull request is created, a later push does not recalculate and does not add people
Recognize only @login A team name (one that contains /) and an email address are skipped
Together with Require approval from all reviewers, require every assigned person to approve before merge CODEOWNERS on its own does not block the merge if that switch is off

When the author is assigned to themselves, they do not get a New Review Request notification. The other reviewers do. That notification says "You have been requested to review Pull Request #…".

3. How to write the file

A CODEOWNERS file can live in three places. AngusGit looks in this order and uses the first file it finds:

  • .github/CODEOWNERS
  • CODEOWNERS at the repository root
  • docs/CODEOWNERS

It reads the file on the pull request's target branch. To merge into main, put the file on main first. A copy that exists only on your own branch does nothing for this pull request.

The file below is an example prepared for this repository. It has not been committed. Use the login @xlliu. Do not write the display name @Angus.

# Files not covered by a later rule
*                  @xlliu

# The service directory at the repository root
/service/          @admin

# SQL in any directory. Written later, so it overrides earlier rules
*.sql              @xlliu @admin
Enter fullscreen mode Exit fullscreen mode

A comment that starts with #, and a comment at the end of a line, is removed. Blank lines are ignored. Separate the path and the people with spaces.

Pattern What it matches
* Every file. On its own line, it is the fallback
/service/ The service directory from the repository root, and the files inside it. A leading / anchors the pattern to the root
*.sql A file ending in .sql in any directory
/docs/**/*.md A .md file at any depth under docs
? One character that is not a slash. v?.txt matches v1.txt

When the same file matches several lines, the last line wins.

  • docs/empty-cart-note.md matches only *, so the person is @xlliu.
  • service/Foo.java matches * first, then /service/, so @admin remains.
  • service/db/init.sql matches all three lines. The last line is *.sql, so @xlliu and @admin remain.

A line that starts with ! is not treated as an exclusion. Brackets are not treated as a character class. They match the brackets as written.

4. Where the switch is

The entry is repository Settings → Pull Requests. The address includes ?tab=settings&section=pullrequests.

Require approval from all reviewers is on. Enable CODEOWNERS is off

What this page shows:

Item State
Require code review On. The description is "Require code review before merging, effective for all branches".
Required reviewers 1
Reviewers 2 reviewer(s) selected: Angus, admin
Require conversation resolution Off
Require approval from all reviewers On. The description is "All assigned reviewers must approve before merging".
Enable CODEOWNERS Off. The description is "Auto-assign reviewers by code path based on the .github/CODEOWNERS file".
Auto-merge when reviews pass On. This pull request must also have Enable auto-merge turned on before it merges by itself. The merge button on #9 is still gray
Auto-assign reviewers (load balancing) Off
Review timeout reminder (hours) 0, which means off

When you turn on Require code review, the count has to be at least 1, and you have to select at least one reviewer. Otherwise save says "When code review is enabled, you must set the number of reviewers and select at least one reviewer". A successful save says "Pull Requests settings saved". If the page already has these values, opening settings is only a look. You do not have to save again.

When load balancing is on, and there are more candidates than Required reviewers, only the people with the fewest unfinished reviews are kept, and the count equals the required number. A code owner can be left out. This repository has it off, so both default reviewers stay.

Require approval from all reviewers looks at every person already assigned, including default reviewers and people added from CODEOWNERS. When the count is 1 and "all reviewers" is off, one approval is enough for the count. This repository has "all reviewers" on, so #9 waits until both Angus and admin approve. The red text on the page now is "Reviews are still pending and must be approved before merge". If a merge is still sent, the API returns All reviewers must approve before merging; "1" reviewer(s) have not approved yet. #9 is still open. Wait until both reviewers approve, then merge.

5. Branch protection

Require code review in repository settings controls whether a pull request can be merged. It does not stop a direct push to main. This repository's Settings → Branch Protection says "No branch protection rules configured". To block a direct push and make changes go through a pull request, click Add rule, turn on reviews for main, and include administrators. The steps are in the branch protection article at the end.

At merge time, if the target branch's protection rule has a review count, that count is used. If it does not, the repository setting Required reviewers is used. Require approval from all reviewers still comes from the repository settings.

6. When people are not assigned by path

What you see Why What to do
Only the default reviewers Enable CODEOWNERS is off, or the target branch has no file in any of the three places. #9 is the first case Merge the file into the target branch, turn the switch on, save, then open a new pull request
The file names people, and the review list does not The text after @ is not a login, or it is a team name or an email Change it to a login such as @xlliu. The display name Angus does not match
The assigned people are not the line you expected The same file matched several lines, and the last line is the one that applies Put the more specific rule later, or write several people on the same line
After creation you changed another directory, and the new person did not appear It is calculated only at creation The author or an administrator adds that person as a reviewer by hand
Someone was merged before they approved Require approval from all reviewers is off, and the approval count already reached the required number Turn on "all reviewers". This repository already has it on

Frequently asked questions

What if a person in CODEOWNERS has no permission on the repository?

They are still added as a reviewer. Opening the pull request and submitting a review requires read permission on this repository.

Does the community edition include this?

Yes. Require code review, Enable CODEOWNERS, and Require approval from all reviewers are all under repository Settings → Pull Requests.

Can either of two people approve, so that one approval is enough?

Write both people on the same line, turn off Require approval from all reviewers, set Required reviewers to 1, and leave load balancing off. One approval is then enough for the count. The cost is that an approval from any assigned person counts, whether or not they are a code owner. This repository currently has "all reviewers" on, so that is not how it counts.

Summary

xlliu/test-pr-example has no CODEOWNERS file, and Enable CODEOWNERS is off. The reviewers on #9, Angus and admin, come from the default list. Both are still pending, and the merge button is unavailable.

To add people by directory: merge .github/CODEOWNERS into the target branch, write rules with @login, and let the last matching line win for a file. Then turn on Enable CODEOWNERS and save. A new pull request combines the people matched in the file with the default reviewers. This repository already has Require approval from all reviewers on, and load balancing is off, so every assigned person has to approve.

Conclusion: Default reviewers are assigned when a pull request is created. CODEOWNERS adds logins by path only after the file is on the target branch and Enable CODEOWNERS is on. When Require approval from all reviewers is on, every one of those people has to approve before the merge.

Related articles

Top comments (0)