In software development, numerous people touch the same code, and it’s crucial to keep track of who is responsible for what. This is where
CODEOWNERS come into play.
CODEOWNERS feature allows you to specify individuals or teams who are responsible for code in a repository, making it easier to manage your projects. This feature can streamline the review process, enhance security, and make sure the right people are responsible for the right code.
In this guide, you’ll learn all about why you need
CODEOWNERS and how to effectively use this feature in your software development workflow.
Why you need CODEOWNERS
In order to outline who is responsible for different sections of a codebase, you need to create a
CODEOWNERS file in your repository. When a pull request (PR) is opened that touches files listed in the
CODEOWNERS file, the designated code owner is automatically asked to review that section of the code. Several popular code hosting platforms support this feature, including GitHub, GitLab, and Bitbucket.
Following are some of the reasons why you should consider implementing
CODEOWNERS into your software project:
- Enhanced security measures: Defining
CODEOWNERScreates a safeguard, ensuring that only designated users or teams can sign off on changes to specific areas of the codebase. This reduces the likelihood of unauthorized or accidental alterations to the code.
- Streamlined review mechanism: When you use
CODEOWNERS, you automate the process of identifying the most appropriate reviewers for each PR. This minimizes delays and ensures that each PR is examined by someone with domain-specific knowledge, elevating the quality of the review.
- Increased sense of accountability: Allocating certain code sections to specific maintainers not only speeds up the review process but also instills a greater sense of responsibility. When you’re a named code owner, you’re more likely to be proactive about code quality, documentation, and other best practices.
- Automated processes for greater efficiency: When you incorporate
CODEOWNERSinto your continuous integration, continuous delivery (CI/CD) workflows, you automate the initial step of code review. This means that the right eyes are reviewing the code quickly, which is crucial for rapid development cycles and high-velocity teams.
When you implement
CODEOWNERS, you’re not merely inserting a file into your repository; you’re fundamentally improving how your project is managed, secured, and maintained.
Getting started with CODEOWNERS
If you have a repository without a
CODEOWNERS file, any member can review a PR without restrictions. This means that critical pieces of code can be modified without proper oversight.
To avoid this situation, you need to create a
CODEOWNERS file using the following steps:
Create a new file named
CODEOWNERS inside a
docs folder at the root of your project. Then add your first entry like this:
When someone opens a PR,
@your-username will be asked to review it.
In this scenario, let’s assume you have a sample GitHub repository with the following structure:
sample-codeowners-test/ |-- docs/ | |-- CODEOWNERS | |-- src/ | |-- hello.py | |-- tests/ | |-- test_hello.py | |-- README.md
Please note: Putting the
CODEOWNERSfile in the
docsfolder applies to both GitHub and GitLab. Additionally, make sure you replace the
@your-usernamewith your username.
To enable or disable
CODEOWNERS in your GitHub repository, you need to define a rule set. To do so, you need to go to your repository Settings and click on Rules > Rulesets in the left navigation bar. Then enable Require a pull request before merging and Require review from Code Owners:
If you’re using GitLab, you can enable
CODEOWNERS on a protected branch. For more information on how to do this, refer to this GitLab documentation:
If you disable the Require review from Code Owners option in your GitHub Settings or if you remove the Require approval from code owners in GitLab, then the PR can be merged without a review from the designated code owners. While this can speed up the merge process, it does so at the expense of code quality and security:
For all the following examples, this option is enabled.
Avoiding common pitfalls with the CODEOWNERS file
Navigating the complexities of repository management can be challenging. Avoiding missteps in the
CODEOWNERS file setup is crucial for streamlined code reviews.
Create a CODEOWNERS file, but leave it empty
If you create a
CODEOWNERS file but leave it empty, no one is assigned to review PRs. While this won’t block the PR process, you lose the advantages of having specified reviewers, which is generally not recommended.
In this scenario, any user with write access can approve code before it’s merged.
Define a path without any users assigned
When setting up a CODEOWNERS file, it’s essential to assign users or teams to specific paths. However, consider this improper configuration:
Here, you define two paths in your
src/*. But you don’t assign any users or teams to it. In this scenario, no one is automatically assigned to review PRs affecting files in the
src directories. This contradicts the purpose of using a
CODEOWNERS file and should be avoided.
Create a team without any members in it
In organizational setups, there may arise a need to initialize a team structure even before members are allocated. Let’s assume the
CODEOWNERS file has the following content:
If you define a team in your
CODEOWNERS file (ie
@your-org/your-empty-team) but that team has no members, the PR will not have any automatic reviewers. In this case, the merge is blocked unless you add a member to the team. It’s best to make sure that each team has at least one member before adding it to your
Using the CODEOWNERS file properly
Effective codebase management requires a deep knowledge of the tools available. This is why it’s crucial to understand how to properly utilize the
CODEOWNERS file, as it facilitates precise delegation of responsibility.
If you have a simple team and want one or two people to be responsible for all code, your
CODEOWNERS file might look like this:
# The user @your-username is the code owner for the entire repository * @your-username
Any PR related to changes in your code needs the approval of
In a larger organization, you might have different departments responsible for different aspects of the code, like this:
# The Engineering department is responsible for all source code src/* @Your-Org/EngineeringTeam # The Quality Assurance team is responsible for all tests tests/* @Your-Org/QATeam # The Documentation team is responsible for the README file /README.md @Your-Org/DocumentationTeam
Any PR related to changes under the
src folder requires the approval of a member from the
@EngineeringTeam. The changes in the
tests folder require approval from a member of the
@QATeam, and the
README.md file require approval from the
Please note: When specifying a team, you need to make sure that this team has
writeaccess to your repository. To define the team’s name, you need to put the organization name followed by a forward slash as well as the team’s name:
Sometimes, you’ll have a hierarchy of responsibilities. In this scenario, you can specify multiple code owners like this:
# The Core team is responsible for the entire codebase * @Your-Org/CoreTeam # But specific modules have additional specialized owners src/hello.py @Your-Org/PythonExperts @Your-Org/CoreTeam # The tests have their own owners, in addition to being under the CoreTeam tests/* @Your-Org/TestTeam @Your-Org/CoreTeam
Here, a change to
src/hello.py requires approval from someone in either
@Your-Org/CoreTeam; whereas changes to something in the
tests folder requires approval from either
You can also negate ownership for specific files or folders like this:
# The Core team is responsible for the entire codebase * @Your-Org/CoreTeam # Except for the hello.py, which is maintained by the Python team /src/hello.py @Your-Org/PythonTeam
In this scenario, the
@Your-Org/CoreTeam is responsible for everything except
src/hello.py, which is the sole responsibility of the
By choosing the right setup for your team’s needs, you can use the
CODEOWNERS file to enforce code quality and ensure that the right people are reviewing changes to different parts of your codebase.
How team and user permissions affect CODEOWNERS
When managing code, understanding permissions is imperative. In simple terms, permissions decide who can do what in a project. Features like
CODEOWNERS use these permissions to decide who can review and approve code changes. In order to use
CODEOWNERS effectively, you need to know how these permissions are set and what they mean.
In GitHub, you can set permissions at an organization level, at the repository level, or within teams. Your
CODEOWNERSsettings are affected by these permissions. For instance, if a user doesn’t have write access to a repo, they can’t be a code owner.
CODEOWNERS feature doesn’t operate in isolation; it’s tied to the permissions model of the platform you’re using. Say you set a team as a code owner, but individual members of that team don’t have the necessary repository-level permissions. In this case, the
CODEOWNERS setting won’t function as expected, and the team members won’t be able to act on the PR in the capacity of a code owner. The same applies to users.
In GitLab, the permission model is similar but uses different naming conventions. You have to be at least a
Maintainer in a project to become a code owner. Similar to GitHub, GitLab also demands a certain level of permissions for a user to be named as a code owner. Notably, the
Maintainer role allows for a broad set of permissions, including the ability to merge code and manage the repository. This is essential for code owners to effectively review and approve code changes.
If you designate a
Developer in GitLab as a code owner, the setting will not take effect because the user doesn’t possess the requisite permissions to enforce code ownership rules. For more information on how it works, check out the GitLab documentation.
Regardless of the platform you’re using, understanding the interplay between
CODEOWNERS and permissions is critical for setting up an effective and secure code review process.
In this article, you learned about the importance of implementing
CODEOWNERS in your projects. Not only does it offer an extra layer of security by designating who can approve changes, but it also streamlines the PR review process and fosters a sense of ownership among project maintainers.
Additionally, integrating a
CODEOWNERS file can bring about a cultural shift within your development team. It encourages clear accountability, ensuring that specific individuals or teams are responsible for particular codebases. This clarity can help prevent code rot since everyone knows who to go to for improvements or bug fixes, enhancing long-term maintainability.
CODEOWNERS can serve as an excellent documentation tool. New team members can immediately understand which parts of the codebase are owned by which teams, easing the onboarding process and enhancing project transparency. It can also help external contributors identify whom they should contact for code-specific queries or clarifications, which fosters a more collaborative environment.
Aviator: Automate your cumbersome processes
Aviator automates tedious developer workflows by managing git Pull Requests (PRs) and continuous integration test (CI) runs to help your team avoid broken builds, streamline cumbersome merge processes, manage cross-PR dependencies, and handle flaky tests while maintaining their security compliance.
There are 4 key components to Aviator:
- MergeQueue – an automated queue that manages the merging workflow for your GitHub repository to help protect important branches from broken builds. The Aviator bot uses GitHub Labels to identify Pull Requests (PRs) that are ready to be merged, validates CI checks, processes semantic conflicts, and merges the PRs automatically.
- ChangeSets – workflows to synchronize validating and merging multiple PRs within the same repository or multiple repositories. Useful when your team often sees groups of related PRs that need to be merged together, or otherwise treated as a single broader unit of change.
- TestDeck – a tool to automatically detect, take action on, and process results from flaky tests in your CI infrastructure.
- Stacked PRs CLI – a command line tool that helps developers manage cross-PR dependencies. This tool also automates syncing and merging of stacked PRs. Useful when your team wants to promote a culture of smaller, incremental PRs instead of large changes, or when your workflows involve keeping multiple, dependent PRs in sync.