Set up and use code owners

About code owners

Code owners allows you to define individuals or teams that are responsible for code in a repository, by adding the .bitbucket/CODEOWNERS file to a repository and using a .gitignore-like syntax to map code paths to individuals and teams. The information you provide is then used to automatically assign the best-suited reviewers to Bitbucket pull requests based on what is being changed.

Set up your CODEOWNERS file

Create the CODEOWNERS file in a directory called .bitbucket at the root of your repository. Once you have committed that file to your repository, newly created pull requests that target a branch which has the`CODEOWNERS` file will automatically add suggested reviewers based on the logic you’ve provided.

To start, you can populate the CODEOWNERS file with the full example of the CODEOWNERS file we’ve provided below, or continue reading for specification details and create your own from scratch.

Anatomy of CODEOWNERS

Comments

Comments begin with a # and can be at the start of line or inline with any text, though for readability purposes inline comments typically come at the end of a line.

1 # Im a comment!

Path mapping

Each line in the file should be a path pattern followed by one or many user references. Patterns follow most of the same rules as .gitignore syntax with the following exceptions (which do not work in CODEOWNERS files):

  • Escaping a pattern starting with # using \ so it is treated as a pattern and not a comment

  • Using ! to negate a pattern

  • Using [ ] to define a character range

User references all need to be on the same line as any newline delimiter will be parsed as a new ownership rule. Multiple user references for a single pattern should be space-delimited.

1 2 3 4 # Each line is a file pattern followed by one or more owners. # Pattern matching rules are approximately the same as .gitignore syntax * individual@example.com individual2@example.com

User references

Users can be referenced either by email address, username, group name, or team name (more on this later). Email addresses should simply be formatted as normal email addresses, usernames are prefixed with a single @ symbol, and groups are prefixed with the slug of the containing workspace followed by a slash and the name of the group.

1 2 3 foo.py individual@example.com # Plain email addresses bar.py @individual-username # Prefix usernames with `@` baz.py @workspace-slug/group-name # Prefix group names with the workspace name

Precedence

Order is important! The last matching pattern in the CODEOWNERS file has the highest precedence. In the following example, when someone opens a pull request that only modifies javascript files, only @js-owner (and not the global owner) will be requested for a review.

If a pull request was opened with changes to javascript and markdown files was also opened, both rules would match and everyone would be added as reviewers.

1 2 * global-owner1@example.com # Owns all files except *.js *.js js-owner@example.com # Owns only *.js files

Selection strategies

When a parsed ownership rule determines that a group is an owner of the changeset, additional logic is used to select individual owners from that group of users. When no explicit strategy is selected, a single user from the group will be chosen at random.

The available strategies are all, random, and least_busy. The first two add all of the contributors or a random ‘N' number of reviewers where ‘N’ is an optional number passed like random(2)/ least_busy(3) . The least_busy strategy sorts the users by number of open pull requests that they are already reviewing, and then selects the configured number of contributors.

For least_busy and random strategies, omitting the optional parentheses and numeric argument is implicitly the same as explicitly configuring (1).

1 2 3 4 * @workspace-slug/everyone # equivalent to `@workspace-slug/everyone:random(1)` *.js @workspace-slug/frontenders:all *.py @workspace-slug/backenders:least_busy(3) *.sql @workspace-slug/dba:random(1)

Adding teams as code owners

Managing groups and members can often times be out of scope for repository collaborators and contributors in a workspace. In order to allow the full flexibilty of Group references, but without needing elevated privileges in your workspace, you can define a file named teams.yaml adjacent to the CODEOWNERS file in your .bitbucket directory.

This file contains ad-hoc definitions of groups of reviewers that be managed using the same config-as-code paradigm as the CODEOWNERS file.

Example syntax of teams.yaml

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 frontend: # Name of the Team contributors: # Array of contributors by email address - individual@example.com - individual1@example.com - individual2@example.com - individual3@example.com - individual4@example.com - individual5@example.com reviews: # Configuration for selecting PR reviewers strategy: least_busy # Reverse sort by # of open PR's they are reviewing select: 2 # and select the top 2 contributors backend: contributors: - individual@example.com - individual1@example.com reviews: strategy: random # Randomly sort all users select: 1 # and select the top 1 seniors: contributors: - individual4@example.com - individual5@example.com reviews: strategy: all # Select all users, no filtering/sorting applied # No `select` argument required; ignored if specified

The available selection strategies are the same as the group strategies defined above, with the numeric argument instead being defined in the select field. You can then reference these teams in your CODEOWNERS file by prefixing them with the identifier @teams.

Selection strategies in CODEOWNERS take precedence over the strategy defined in teams.yaml. This allows for use-cases such as using all when a specific file has changed.

Example of teams in the codeowners file

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 # User @teams to prefix your team name and let CODEOWNERS know to look in # your teams.yaml file /apps/bitbucket/* @teams/Frontend # Just like with groups, you can select a sub-sampling of your team: /src/frontend/* @teams/Seniors /src/important/* @teams/Seniors:all # Inline strategy overrides `teams.yaml` /src/test/* @teams/Frontend @teams/Backend /src/database/* @teams/Backend # It is possible to mix teams and individual contributors, however the selection # strategies only apply to the teams /src/keys/*.pub @teams/SRE superuser@example.com # It can be useful to setup a "meta-owner" that is responsible for changes to the # teams and CODEOWNERS files .bitbucket/* contributor1@example.com

In the above configuration, a pull request with changes in the src/important and src/test directory would add all of the contributors from the Seniors team, 1 contributor from the Backend team, and 2 contributors from the Frontend team as reviewers on the pull request creation screen.

Your code owners configuration is always read from the destination branch of a pull request. For example, when a pull request targets the main branch, reviewers are assigned based on the CODEOWNERS and teams.yaml files from the main branch.

Full example of a CODEOWNERS file including teams

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 # The CODEOWNERS file shares the same pattern matching syntax for file/directory # names with .gitignore # This is a comment. # Each non-commented line consists of a file pattern followed by one or more owners. # These owners will be the default owners for everything in # the repository. Unless a later match takes precedence. # # global-owner1@example.com and global-owner2@example.com will be requested for # review when someone opens a pull request. # # * global-owner1@example.com global-owner2@example.com # Order is important; the last matching pattern takes the most # precedence. When someone opens a pull request that only # modifies JS files, only js-owner@example.com and not the global # owner(s) will be requested for a review. # # *.js js-owner@example.com # This is an inline comment. # This means that more specific file-level ownership rules # often drift towards the bottom of the file. If this specific # file is changed, Steve Driftexpert will be counted as an owner. Rather # than js-owner as defined above. # # /src/pullrequests/drift.js stevedriftexpert@example.com # Groups can be added as owners, they must be prefixed by # the workspace name. When a group match occurs, a single # random user from that group is chosen by default. # # *.js @group-name/frontenders # If something other than the default behavior for group # matches is wanted, you can explicitly define the # matching strategy. # The available matching strategies are: # random - select N random user(s) from this group # all - select all members of this group # least_busy - select N users(s) sorted by the number of open reviews # Examples: # # Select a configurable number of users at random # *.py @group-name/py-owners:random # same as random(1) *.py @group-name/py-owners:random(3) # 3 random users # # Sort reviewers by # of active PR reviews DESC and select # a configurable number of users in that order. # # *.py @group-name/py-owners:least_busy # Same as least_busy(1) # *.py @group-name/py-owners:least_busy(3) # least-busy 3 people # # Always select the entire group # # *.py @group-name/py-owners:all # Additionally it is possible to define codeowners "teams" by specifying # a yaml file called `teams.yaml` in the same directory as your CODEOWNERS file. # This allows for all of the benefits of Groups, while keeping the configuration # for this collection of users entirely within the repository. # # The contents of this file should be a map of team names that have a `contributors` # and a `reviews` key that specify the email addresses of team members and the # the reviewer selection configuration. # # cat .bitbucket/teams.yaml # # Frontend: # Name of the Team # contributors: # Array of contributors by email address # - user1@example.com # - user2@example.com # - user3@example.com # - user4@example.com # - user5@example.com # - user6@example.com # reviews: # Configuration for selecting PR reviewers # strategy: least_busy # Reverse sort by # of open PR's they are reviewing # select: 2 # and select the top 2 contributors # Backend: # contributors: # - user7@example.com # - user8@example.com # reviews: # strategy: random # Randomly sort all users # select: 1 # and select the top 1

Additional Help