doc/user/project/codeowners/reference.md
{{< details >}}
{{< /details >}}
The CODEOWNERS file uses a syntax to define ownership rules.
Each line in the file represents a rule, and specifies a file path pattern and one or more owners.
The key elements are:
# are ignored. Inline comments are unsupported.
Any Code Owners listed in a comment are parsed.[Section name].[!note] If an entry is duplicated in a section, the last entry is used. Rules defined later in the file take precedence over earlier rules.
Here are some examples:
# Specify a default Code Owner for all files with a wildcard:
* @default-owner
# Specify multiple Code Owners to a specific file:
README.md @doc-team @tech-lead
# Specify a Code Owner to all files with a specific extension:
*.rb @ruby-owner
# Specify Code Owners with usernames or email addresses:
LICENSE @legal [email protected]
# Use group names to match groups and nested groups:
README @group @group/with-nested/subgroup
# Specify a Code Owner to a directory and all its contents:
/docs/ @all-docs
/docs/* @root-docs
/docs/**/*.md @markdown-docs # Match specific file types in any subdirectory
/db/**/index.md @index-docs # Match a specific file name in any subdirectory
# Use a section to group related rules:
[Documentation]
ee/docs @docs
docs @docs
# Assign a role as a Code Owner:
/config/ @@maintainer
In a CODEOWNERS file, sections are named areas that are analyzed separately,
and always enforced. Until you define a section, GitLab treats your entire CODEOWNERS file
as a single section.
Adding more sections changes how GitLab evaluates the file:
For example, in a CODEOWNERS file with sections that define the Code Owners of a README file:
* @admin
[README Owners]
README.md @user1 @user2
internal/README.md @user4
[README other owners]
README.md @user3
README.md in the root directory are:
@admin, from the unnamed section.@user1 and @user2, from [README Owners].@user3, from [README other owners].internal/README.md are:
@admin, from the unnamed section.@user4, from [README Owners]. Both README.md and internal/README.md entries in this
section match the file, but only the last matching entry in the section is used.@user3 from [README other owners].To add a section to the CODEOWNERS file, enter a section name in square brackets,
followed by the files or directories, and users, groups, or subgroups:
[README Owners]
README.md @user1 @user2
internal/README.md @user2
Each Code Owner in the merge request widget is listed under a label.
The following image shows Default, Frontend, and Technical Writing sections:
For more section configuration options, see:
Section headings must have a name. Section names are case-insensitive, and sections with duplicate names are combined. For protected branches only, they can:
^).Examples:
# Required section
[Section name]
# Optional section
^[Section name]
# Section requiring 5 approvals
[Section name][5]
# Section with @username as default owner
[Section name] @username
# Section with @group and @subgroup as default owners and requiring 2 approvals
[Section name][2] @group @subgroup
If multiple file paths inside a section share the same ownership, define default Code Owners for the section. All paths in that section inherit this default, unless you override the section default on a specific line.
Default owners are applied when specific owners are not specified for file paths. Specific owners defined beside the file path override default owners.
For example:
[Documentation] @docs-team
docs/
README.md
[Database] @database-team @agarcia
model/db/
config/db/database-setup.md @docs-team
In this example:
@docs-team owns all items in the Documentation section.@database-team and @agarcia own all items in the Database section except
config/db/database-setup.md, which has an override assigning it to @docs-team.Compare this behavior to when you use regular entries and sections together, when entries in sections don't override entries without sections.
You can designate optional sections in your Code Owners file. Optional sections enable you to designate responsible parties for various parts of your codebase, but not require approval from them. This approach provides a more relaxed policy for parts of your project that are frequently updated, but don't require stringent reviews.
To treat the entire section as optional, prepend the section name with the caret ^ character.
In this example, the [Go] section is optional:
[Documentation]
*.md @root
[Ruby]
*.rb @root
^[Go]
*.go @root
The optional Code Owners section displays in merge requests under the description:
If a section is duplicated in the file, and one of them is marked as optional and the other isn't, the section is required.
Optional sections in the CODEOWNERS file are treated as optional only
when changes are submitted by using merge requests. If a change is submitted directly
to the protected branch, approval from Code Owners is still required, even if the
section is marked as optional.
Eligibility rules determine who can be a valid code owner. Specific rules apply depending on the
reference method in the CODEOWNERS file: username, group, or role.
To be eligible as code owners, users referenced by their username (@username) must be authorized
for the project. The following rules apply:
When referencing a group with group name (@group_name) or nested group name (@nested/group/names),
the following rules apply:
When referencing a role (@@role), the following rules apply:
@@developer does not include
users with Maintainer or Owner roles.For more information about complex group inheritance and eligibility, see group inheritance and eligibility.
{{< history >}}
codeowner_role_approvers.codeowner_role_approvers removed.{{< /history >}}
You can add or set a role for direct project members as Code Owners:
@@ prefix to set a role.@@developer
does not include users with Maintainer or Owner roles.@@developers is accepted.The following example sets all direct project members with the Developer or Maintainer
role as Code Owners for file.md:
Open the CODEOWNERS file.
Add a line using the following pattern:
file.md @@developer @@maintainer
Save the file.
Commit and merge the changes.
You can set direct members of a group or subgroup as a Code Owner. For more information about group membership, see membership types.
Prerequisites:
To set direct members of a group or subgroup as a Code Owner:
Open the CODEOWNERS file.
Enter text that follows one of these patterns:
# All direct group members as Code Owners for a file
file.md @group-x
# All direct subgroup members as Code Owners for a file
file.md @group-x/subgroup-y
# All direct group and direct subgroup members as Code Owners for a file
file.md @group-x @group-x/subgroup-y
Save the file.
Commit and merge the changes.
[Maintainers]
* @gitlab-org/maintainers/group-name
In this example:
The group group-name is listed under the [Maintainers] section.
The group-name contains the following direct members:
In the merge request approval widget, the same direct members are listed as Maintainers:
[!note] When global SAML group memberships lock is enabled, you cannot set a group or subgroup as a Code Owner. For more information, see incompatibility with Global SAML group memberships lock.
If you encounter issues, see user not shown as possible approver.
Paths can be absolute, relative, directory, wildcard, or globstar, and are matched against the repository root.
Paths starting with / match from the repository root:
# Matches only README.md in the root.
/README.md
# Matches only README.md inside the /docs directory.
/docs/README.md
Paths without a leading / are treated as globstar paths:
# Matches /README.md, /internal/README.md, /app/lib/README.md
README.md @username
# Matches /internal/README.md, /docs/internal/README.md, /docs/api/internal/README.md
internal/README.md
[!note] When using globstar paths, be cautious of unintended matches. For example,
README.mdwithout a leading/matches anyREADME.mdfile in any directory or subdirectory of the repository.
End a path with / to match all files in the directory and its subdirectories:
# Matches all files in /docs/ and its subdirectories
/docs/
Use * to match multiple characters:
# Any markdown files in the docs directory
/docs/*.md @username
# /docs/index file of any filetype
# For example: /docs/index.md, /docs/index.html, /docs/index.xml
/docs/index.* @username
# Any file in the docs directory with 'spec' in the name.
# For example: /docs/qa_specs.rb, /docs/spec_helpers.rb, /docs/runtime.spec
/docs/*spec* @username
# README.md files one level deep within the docs directory
# For example: /docs/api/README.md
/docs/*/README.md @username
Use ** to match files or patterns across multiple directory levels:
# For example: /docs/index.md, /docs/api/index.md, and /docs/api/graphql/index.md.
/docs/**/index.md
To match all files in a directory,
use directory paths with a trailing slash (/).
{{< history >}}
codeowners_file_exclusions.codeowners_file_exclusions removed.{{< /history >}}
Prefix files or paths with ! to exempt or exclude them from requiring code owner approval.
Exclusions apply in their section. In the following example:
pom.xml exclusion applies to the default section./config/**/*.rb exclusion only affects Ruby files in the Ruby section.# All files require approval from @username
* @username
# Except pom.xml which needs no approval
!pom.xml
[Ruby]
# All ruby files require approval from @ruby-team
*.rb @ruby-team
# Except Ruby files in the config directory
!/config/**/*.rb
The following guidelines explain how exclusion patterns behave:
Exclusions are evaluated in order in their section. For example:
* @default-owner
!*.rb # Excludes all Ruby files.
/special/*.rb @ruby-owner # This won't take effect as *.rb is already excluded.
After a pattern is excluded, it cannot be included again in the same section:
[Ruby]
*.rb @ruby-team # All Ruby files need Ruby team approval.
!/config/**/*.rb # Ruby files in config don't need Ruby team approval.
/config/routes.rb @ops # This won't take effect as config Ruby files are excluded.
Files matching an exclusion pattern do not require code owner approval for that section. If you need different exclusions for different owners, use multiple sections:
[Ruby]
*.rb @ruby-team
!/config/**/*.rb # Config Ruby files don't need Ruby team approval.
[Config]
/config/ @ops-team # Config files still require ops-team approval.
Use exclusions for files that are automatically updated:
* @default-owner
# Files updated by automation don't need approval.
!package-lock.json
!yarn.lock
!**/generated/ # Any files in generated directories.
!.gitlab-ci.yml
Entries must have one or more owners These can be groups, subgroups, and users.
/path/to/entry.rb @group
/path/to/entry.rb @group/subgroup
/path/to/entry.rb @user
/path/to/entry.rb @group @group/subgroup @user
For more information about adding groups as Code Owners, see add a group as a Code Owner.