CODEOWNERS File
The CODEOWNERS file is critical in the implementation of Code Ownership principles. It is a plain text file that maps specific code files and directories to their designated Code Owners.
The file is usually located at the root directory of a project's repository. For
the Native Apps project, it can be found inside the .gitlab/
directory. You
can also view it directly by following
this
link to the Native Apps project in Gitlab.
The CODEOWNERS file structure
The CODEOWNERS file requires a specific structure to be used for the information added to it. This is important because GitLab uses the file to automatically identify whether changes in a merge request are associated with any code owners listed in the file.
At its most basic, the file consists of lines of pairs of file paths on the left and code owners on the right, like so:
*.js @joe.citizen
In the example above, The user "Joe Citizen" in Gitlab would be marked as code
owner for all JavaScript files (denoted by using the *.js
glob
pattern).
Multiple owners can be listed per file path, separated by a single space character, and multiple path and owner pairs can be listed, on separate lines
[Project -> Documentation]
# Documentation for the project itself including the README, etc.
decisions/ @john.hatvani @rhys.geary @charles.harwood @filip.maslovaric @alex.little @wenchao.chen
README.md @john.hatvani @rhys.geary @charles.harwood @filip.maslovaric @alex.little @wenchao.chen
[Native Modules -> Android Keyboard Adjust]
# Custom native module for android keyboard adjust settings on the fly
app/hooks/useAndroidKeyboardAdjustResize.ts @charles.harwood
app/modules/native/android-keyboard-adjust.ts @charles.harwood
In the example above, taken directly from the Native Apps' own CODEOWNERS file,
each of the listed @user.names
next to a file/or/folder/path
will be the
Code Owners for the files or folders under that path.
*.js @joe.citizen # Code Owner for all JavaScript files
**/brand/** @patrick.star # Code Owner for all files and folders under the **/brand subfolder
config/ @master.mind # Code Owner for all files and folders under the config/ folder, etc...
Notice also that comments can be left throughout to make things easier to
understand or add additional details by prefixing the comment text with a hash
(#
).
Each sentence enclosed in square brackets ([]
), becomes a Code Ownership
section, allowing to list multiple paths and owners for a given domain and
have them organised under a single Code Ownership section when looking at Code
Owners approvals in a Merge Request.
[Testing]
**/__snapshots__/** @jane.tester @warren.worrywart
**/__tests__/** @jane.tester @warren.worrywart
.jest/ @jane.tester @warren.worrywart
*.test.ts @jane.tester @warren.worrywart
Code Owners Approvals
When contributing changes to the codebase, the CODEOWNERS file is where we look to determine which owner should review and evaluate those changes. The relevant Code Owner(s) can then provide feedback and determine whether to approve or reject the changes. This streamlines the code change process, ensuring that changes are reviewed by the right individual(s) with the relevant knowledge and expertise.
Gitlab makes it even more straightforward to use the CODEOWNERS file: proposed changes in the codebase will automatically trigger Gitlab to evaluate the file, and the correct Code Owner(s) will be identified and requested to review the changes in the Merge Request approval section. This saves time and reduces manual effort, making the code review process more efficient.
Effect of code owners approvals on merge request approval requirements
If changes being contributed in a Merge Request touch upon any paths that fall under a code ownership, then those code owners will be prompted to review and approve the changes for their owned files/folder paths in the Merge Request.
If the changes span more than one code ownership, then each will require owners to review and approve changes relevant to their code ownership. If your MR touches upon 2 different code ownerships (e.g. Feature A and Feature B that are owned separately), then the approval requirements would go as follows:
- 2 approvals from "Any eligible approvers"
- Can be anyone from the @technology Gitlab Group, which is everyone in the department Can be set to more or less approvals in Merge Request Approvals settings for the project
- Code Owners count as "any eligible approvers"
- At least 1 approval from "Feature A" code owners
- At least 1 approval from "Feature B" code owners
The total required approvals is therefore still 2 approvals, but of those two, at least 1 must come from each feature. If 2 approvals came from elsewhere, you'd still need the code owners approvals. Its the same as currently with our manual approver rules for core ticks where you can have many "Any eligible approvers" but you still need at least 1 core tick for the MR to be able to be merged.
To learn more about how Code Ownership, Code Owners Approvals and the Code Owners file work in projects hosted through Gitlab, visit Gitlab's Code Owners documentation page.
Maintaining the CODEOWNERS file
Keeping the CODEOWNERS file updated is critical to the effective operation of Code Ownership in a project.
By ensuring that the listed code paths and Code Owners are accurate, code contributors will know the appropriate person to reach out to when proposing changes, and Gitlab will be able to automatically assign correct Code Owners for review approvals in Merge Requests, eliminating the need for manual searching of who should review and approve the changes.
CODEOWNERS Template file
In the Native Apps project, the Code Owners Template file is used to assign code ownerships in the project's codebase, and keep the map of owners and owned domains up to date.
The template file serves as a workaround to a limitation in GitLab that affects how Code Owners are displayed in Merge Request approval sections when the code owners for a given path are a Gitlab Group rather than individual Gitlab users.
# Example of CODEOWNERS paths, in a code owners section, assigned to a Gitlab Group,
# rather than individual users
[Group Mode]
group-betting/ @technology/team-groups/native-apps-approvers/group-mode
group-mode/ @technology/team-groups/native-apps-approvers/group-mode
When a GitLab Group is listed as a Code Owner, its members do not appear in MRs due to how GitLab and our code projects are set up. Gitlab is meant to parse the Gitlab Group name in the CODEOWNERS file, and list out the individual group members as the code owners for that given code ownership file/folder path. Instead, the code ownership is correctly displayed in the review approvals section, but the list of users appears black. To see more details about this particular issue, visit this Gitlab Issue.
As restructuring all of our current GitLab-hosted projects is not feasible and the issue remains unresolved on GitLab's side, we use this template file to programmatically populate the CODEOWNERS file with individual Code Owners by their GitLab username.
# Example of the same CODEOWNERS paths, in the same code owners section, assigned to
# individual Gitlab users instead of Gitlab Groups
[Group Mode]
group-betting/ @charles.harwood @roscoe.hart
group-mode/ @charles.harwood @roscoe.hart
Instead of editing the CODEOWNERS file directly, the JSON-based template file allows us to structure the various code ownership sections, paths, and owners themselves much more efficiently, without having to read through a lot of repeated text when trying to track down individual owners that may need updating.
Using this template file to manage the Code Ownership mapping also makes it possible for future tooling to easily manage, report on, or visualise ownership in the project by reading JSON structured data rather than parsing the CODEOWNERS file plain text content.
How to update CODEOWNERS using the Code Owners Template and Groups files
Updating the CODEOWNERS file is simple:
- Edit the Code Owners Template, file rather than the CODEOWNERS file itself, following the same existing file structure you see.
- If you need to update a group of code owners,edit the Code Owners Groups
file.
- Mention the relevant code owner group (e.g.
group:platform-team
), if its not already in the code owners template file, as needed.
- Mention the relevant code owner group (e.g.
- Run the Code Owners generator script,
yarn codeowners:generate
, in a terminal window pointed at the root of the Native Apps project folder. - Verify that the CODEOWNERS file has been successfully re-written, that the changes you've made in the template file are reflected in the CODEOWNERS file itself.
- If the CODEOWNERS file was successfully updated, commit any changes you've made to the template and groups files and the CODEOWNERS file itself in a new branch.
- Submit the changes in a Merge Request.
Follow the links above to see the files themselves in the Native Apps project repository, where you can see how they are currently structured.
Excerpt from the Code Owners Template file:
{
"comments": "For documentation on CODEOWNERS, see https://docs.gitlab.com/ee/user/project/code_owners.html\n\nNOTE: Each code owner must be listed individually (not as a Gitlab group) due to some issues\nwith how Gitlab interprets and presents user groups as owners in Merge Request reviews.",
"sections": [
{
"name": "CODEOWNERS File and Scripts",
"ownerships": [
{
"path": "CODEOWNERS",
"owners": [
"group:platform-team"
]
},
{
"path": "code-owners/",
"owners": [
"group:platform-team"
]
}
],
"comments": "For defining the default owners for different parts of the repository."
},
The Code Owners template file structure is described as follows:
- The JSON file must be an object with a "comments" field (optional) and a
"sections" (required) field.
- The "comments" field, if present, must be a string.
- The "sections" field must be an array of objects, each representing a code ownership section.
- Each code ownership section must have a "name" field and an "owners" field.
- The "name" field must be a string.
- The "owners" field must be an array of objects, each representing a code ownership assignment.
- Each code ownership assignment must have a "path" field and an "owners" field.
- The "path" field must be a string.
- The "owners" field must be an array of strings, where each string is either a code owner identifier starting with "@" or a code owner group identifier starting with "group:".
- Each code ownership section can also have an optional "comments" field, which if present, must be a string.
When updating existing or adding new sections, paths and ownerships, simply make your changes to the template file, following the above required format.
Example of adding a new section, with a new code ownership path, and code owners for said path:
"sections": [
...
{
"name": "New Section Name",
"ownerships": [
{
"path": "path/to/some/file/or/folder",
"owners": [
"group:owner-group-name",
"@individual.user"
]
},
],
"comments": "Groups and individual code owners can be listed together! Useful when a code owner isn't part of any group or entire groups don't intersect well for the code ownership in question"
},
The order in which you insert new objects within any field of the template which is an Array will determine the order in which they appear within the CODEOWNERS file itself.
Any changes made to the CODEOWNERS file directly can be overwritten by running the yarn codeowners:generate
script, as it will re-write the entire file.
Regenerating the Code Owners Template file by reading the CODEOWNERS file
:::Danger This is something you should never have to do under normal circumstances. :::
Should you ever need to re-generate the Code Owners Template file, you can do so
by running the following
script
in a terminal window: yarn codeowners:generate-template
This script operates in reverse, reading the actual Code Owners file and creating or updating the Code Owners Template file. This allows for the recreation of the template file if needed, or its update if the change is easier to make in the Code Owners file first. The structure of the Code Owners file must remain the same for the script to work correctly, otherwise the actual script itself will need to be updated first, and the codeowners generator script as well.
Using Code Owners responsibly
When using the Code Owners file, it's crucial to understand that Code Ownership is not about restricting access to code, but rather creating a collaborative, inclusive, and learning-oriented environment. Code Owners should take on the role of gardeners and teachers, ensuring that their code is well-maintained, well-documented, and that they share their wisdom and expertise with others.
The Code Owners file serves as a clear communication tool, helping all project participants understand who is responsible for specific parts of the code. It also guarantees that changes made to the code are reviewed by the appropriate Code Owner, who can provide guidance and feedback, helping others grow and learn as they contribute to the project.