---
title: Code owners
toc_max_heading_level: 6
tags: [code, owners, codeowners]
---

import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import VersionLabel from '@site/src/components/Docs/VersionLabel';

<VersionLabel version="1.8.0" header />

Code owners enables companies to define individuals, teams, or groups that are responsible for code
in a repository. This is useful in ensuring that pull/merge requests are reviewed and approved by a
specific set of contributors, before the branch is merged into the base branch.

With that being said, moon _does not_ implement a custom code owners solution, and instead builds
upon the popular `CODEOWNERS` integration in VCS providers, like GitHub, GitLab, and Bitbucket.

## Defining owners

With moon, you _do not_ modify a `CODEOWNERS` file directly. Instead you define owners _per project_
with [`moon.*`](../config/project), or globally with [`.moon/workspace.*`](../config/workspace).
These owners are then aggregated and automatically
[synced to a `CODEOWNERS` file](#generating-codeowners).

:::info

An owner is a user, team, or group unique to your VCS provider. Please refer to your provider's
documentation for the correct format in which to define owners.

:::

### Project-level

For projects, we support an [`owners`](../config/project#owners) setting in
[`moon.*`](../config/project) that accepts file patterns/paths and their owners (contributors
required to review), as well as operational settings for minimum required approvals, custom groups,
and more.

Paths configured here are relative from the project root, and will be prefixed with the project
source (path from workspace root to project root) when the file is synced.

```yaml title="packages/components/moon.yml"
owners:
  requiredApprovals: 2
  paths:
    'src/': ['@frontend', '@design-system']
    '*.config.js': ['@frontend-infra']
    '*.json': ['@frontend-infra']
```

The configuration above would generate the following:

<Tabs
  groupId="codeowners"
  defaultValue="github"
  values={[
    { label: 'GitHub', value: 'github' },
    { label: 'GitLab', value: 'gitlab' },
    { label: 'Bitbucket', value: 'bitbucket' },
  ]}
>
<TabItem value="github">

```shell title=".github/CODEOWNERS"
# components
/packages/components/src/ @frontend @design-system
/packages/components/*.config.js @frontend-infra
/packages/components/*.json @frontend-infra
```

</TabItem>
<TabItem value="gitlab">

```shell title=".gitlab/CODEOWNERS"
# components
[components][2]
/packages/components/src/ @frontend @design-system
/packages/components/*.config.js @frontend-infra
/packages/components/*.json @frontend-infra
```

</TabItem>
<TabItem value="bitbucket">

```shell title=".bitbucket/CODEOWNERS"
# components
/packages/components/src/ @frontend @design-system
/packages/components/*.config.js @frontend-infra
/packages/components/*.json @frontend-infra
```

</TabItem>
</Tabs>

### Workspace-level

Project scoped owners are great but sometimes you need to define owners for files that span across
all projects, or files at any depth within the repository. With the
[`codeowners.globalPaths`](../config/workspace#globalpaths) setting in
[`.moon/workspace.*`](../config/workspace), you can do just that.

Paths configured here are used as-is, allowing for full control of what ownership is applied.

```yaml title=".moon/workspace.yml"
codeowners:
  globalPaths:
    # All files
    '*': ['@admins']
    # Config folder at any depth
    'config/': ['@app-platform']
    # GitHub folder at the root
    '/.github/': ['@infra']
```

The configuration above would generate the following at the top of the file (is the same for all
providers):

<Tabs
  groupId="codeowners"
  defaultValue="github"
  values={[
    { label: 'GitHub', value: 'github' },
    { label: 'GitLab', value: 'gitlab' },
    { label: 'Bitbucket', value: 'bitbucket' },
  ]}
>
<TabItem value="github">

```shell title=".github/CODEOWNERS"
# (workspace)
* @admins
config/ @app-platform
/.github/ @infra
```

</TabItem>
<TabItem value="gitlab">

```shell title=".gitlab/CODEOWNERS"
# (workspace)
* @admins
config/ @app-platform
/.github/ @infra
```

</TabItem>
<TabItem value="bitbucket">

```shell title=".bitbucket/CODEOWNERS"
# (workspace)
* @admins
config/ @app-platform
/.github/ @infra
```

</TabItem>
</Tabs>

## Generating `CODEOWNERS`

Code owners is an opt-in feature, and as such, the `CODEOWNERS` file can be generated in a few ways.
The first is manually, with the [`moon sync codeowners`](../commands/sync/code-owners) command.

```shell
$ moon sync codeowners
```

While this works, it is a manual process, and can easily be forgotten, resulting in an out-of-date
file.

An alternative solution is the [`codeowners.sync`](../config/workspace#sync) setting in
[`.moon/workspace.*`](../config/workspace#codeowners), that when enabled, moon will automatically
generate a `CODEOWNERS` file when a [target](../concepts/target) is ran.

```yaml title=".moon/workspace.yml"
codeowners:
  sync: true
```

> The format and location of the `CODEOWNERS` file is based on the
> [`vcs.provider`](../config/workspace#provider) setting.

## FAQ

### What providers or formats are supported?

The following providers are supported, based on the [`vcs.provider`](../config/workspace#provider)
setting.

- [Bitbucket](https://support.atlassian.com/bitbucket-cloud/docs/set-up-and-use-code-owners/) (native
  code owners, uses the same syntax as GitHub)
- Bitbucket (legacy) — the `bitbucket-legacy` provider, for the 3rd-party
  [DevSensei / Code Owners for Bitbucket](https://marketplace.atlassian.com/apps/1218598/code-owners-for-bitbucket?tab=overview&hosting=cloud)
  app, which uses a root `CODEOWNERS` and the `Check()` syntax
- [GitHub](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners)
- [GitLab](https://docs.gitlab.com/ee/user/project/codeowners/reference.html)
- Other (very basic syntax)

:::warning

The `bitbucket` provider now targets Bitbucket's native code owners (`.bitbucket/CODEOWNERS`,
GitHub-compatible syntax). If you were relying on the
[DevSensei / Code Owners for Bitbucket](https://marketplace.atlassian.com/apps/1218598/code-owners-for-bitbucket?tab=overview&hosting=cloud)
app (root `CODEOWNERS` with the `Check()` syntax), set `vcs.provider` to `bitbucket-legacy` to keep
the previous output.

:::

### Where does the `CODEOWNERS` file get created?

The location of the file is dependent on the configured provider.

- GitHub -> `.github/CODEOWNERS`
- GitLab -> `.gitlab/CODEOWNERS`
- Bitbucket -> `.bitbucket/CODEOWNERS`
- Everything else (including `bitbucket-legacy`) -> `CODEOWNERS`

### Why are owners defined in `moon.*` and not an alternative like `OWNERS`?

A very popular pattern for defining owners is through an `OWNERS` file, which can appear in any
folder, at any depth, within the repository. All of these files are then aggregated into a single
`CODEOWNERS` file.

While this is useful for viewing ownership of a folder at a glance, it incurs a massive performance
hit as we'd have to constantly glob the _entire_ repository to find all `OWNERS` files. We found it
best to define owners in `moon.*` instead for the following reasons:

- No performance hit, as we're already loading and parsing these config files.
- Co-locates owners with the rest of moon's configuration.
- Ownership is now a part of the project graph, enabling future features.
