- Example
CODEOWNERS
file - Code Owner file loading
- Pattern matching
- Path matching
- Entry owners
- Error handling
- Related topics
Code Owners syntax and error handling
The Code Owners configuration is stored in a CODEOWNERS
file.
This file determines who should review and approve changes.
This page describes the syntax and error handling used in CODEOWNERS
files and provides examples of how to use them.
Example CODEOWNERS
file
# This is an example of a CODEOWNERS file.
# Lines that start with `#` are ignored.
# Specify a default Code Owner by using a wildcard:
* @default-codeowner
# Specify multiple Code Owners by using a tab or space:
* @multiple @code @owners
# Rules defined later in the file take precedence over earlier rules.
# For example, for all files with a filename ending in `.rb`:
*.rb @ruby-owner
# Files with a `#` can still be accessed by escaping the pound sign:
\#file_with_pound.rb @owner-file-with-pound
# You can use both usernames or email addresses to match users:
LICENSE @legal janedoe@gitlab.com
# Use group names to match groups, and nested groups:
README @group @group/with-nested/subgroup
# Specify Code Owners for directories:
/docs/ @all-docs
/docs/* @root-docs
/docs/**/*.md @root-docs
# Match directories nested anywhere in the repository:
lib/ @lib-owner
# Match only a directory in the root of the repository:
/config/ @config-owner
# If the path contains spaces, escape them like this:
path\ with\ spaces/ @space-owner
# Code Owners sections:
[Documentation]
ee/docs @docs
docs @docs
[Development] @dev-team
*
README.md @docs-team
data-models/ @data-science-team
# This section is combined with the previously defined [Documentation] section:
[DOCUMENTATION]
README.md @docs
Code Owner file loading
The CODEOWNERS
file is loaded from the target branch.
GitLab checks these locations in your repository in this order:
- Root directory:
./CODEOWNERS
- Documentation directory:
./docs/CODEOWNERS
-
.gitlab
directory:./.gitlab/CODEOWNERS
The first CODEOWNERS
file found is used, and all others are ignored.
Pattern matching
GitLab uses File::fnmatch
with the File::FNM_DOTMATCH
and File::FNM_PATHNAME
flags set for pattern matching:
- The repository structure is treated like an isolated file system.
- The patterns follow a subset of shell filename globbing rules, and are not regular expressions.
- The
File::FNM_DOTMATCH
flag allows*
to match dotfiles like.gitignore
. - The
File::FNM_PATHNAME
flag prevents*
from matching the/
path separator. -
**
matches directories recursively. For example,**/*.rb
matchesconfig/database.rb
andapp/controllers/users/stars_controller.rb
.
Comments
Lines beginning with #
are ignored:
# This is a comment
Sections
Sections are groups of entries. A section begins with a section heading in square brackets [ ]
:
[Section name]
/path/of/protected/file.rb @username
/path/of/protected/dir/ @group
Section headings
Section headings must have a name. For protected branches only, they can:
- Require approval (default).
- Be optional (prefixed with
^
). - Require a specific number of approvals. For more information, see Group inheritance and eligibility and Approvals shown as optional.
- Include default owners.
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
Section names
Section names are case-insensitive and defined between square brackets. Sections with duplicate names are combined.
Code Owner entries
Each entry includes a path followed by one or more owners.
README.md @username1 @username2
Path matching
Paths can be absolute, relative, wildcard, or globstar, and are matched against the repository root.
Relative paths
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
README.md
without a leading /
matches any README.md
file in any directory or subdirectory of the repository.Absolute paths
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
Directory paths
Paths ending with /
match any file in the directory:
# This is the same as `/docs/**/*`
/docs/
Wildcard paths
Use wildcards 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
Globstar paths
Use **
to match zero or more directories recursively:
# Matches /docs/index.md, /docs/api/index.md, and /docs/api/graphql/index.md.
/docs/**/index.md
Entry owners
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 on adding groups as Code Owners, see Add a group as a Code Owner.
Error handling
- Error validation introduced in GitLab 16.3.
Entries with spaces
Escape whitespace in paths with backslashes:
path\ with\ spaces/*.md @owner
Without escaping, GitLab parses folder with spaces/*.md @group
as: path: "folder", owners: " with spaces/*.md @group"
.
Unparsable sections
If a section heading cannot be parsed, the section is:
- Parsed as an entry.
- Added to the previous section.
- If no previous section exists, the section is added to the default section.
After the default section
* @group
[Section name
docs/ @docs_group
GitLab recognizes the heading [Section name
as an entry. The default section includes 3 rules:
- Default section
-
*
owned by@group
-
[Section
owned byname
-
docs/
owned by@docs_group
-
After a named section
[Docs]
docs/**/* @group
[Section name
docs/ @docs_group
GitLab recognizes the heading [Section name
as an entry. The [Docs]
section includes 3 rules:
-
docs/**/*
owned by@group
-
[Section
owned byname
-
docs/
owned by@docs_group
Malformed owners
Each entry must contain one or more owners. Malformed owners are invalid and ignored:
/path/* @group user_without_at_symbol @user_with_at_symbol
This entry is owned by @group
and @user_with_at_symbol
.
Inaccessible or incorrect owners
GitLab ignores inaccessible or incorrect owners. For example:
* @group @grou @username @i_left @i_dont_exist example@gitlab.com invalid@gitlab.com
If only @group
, @username
, and example@gitlab.com
are accessible, GitLab ignores the others.
Zero owners
If an entry includes no owners, or zero accessible owners exist, the entry is invalid. Because this rule can never be satisfied, GitLab auto-approves it in merge requests.
Require code owner approval
enabled, rules with
zero owners are still honored.Minimum approvals
When defining the number of approvals for a section,
the minimum number of approvals is 1
. Setting the number of approvals to
0
results in GitLab requiring one approval.