Функция CODEOWNERS позволяет определить ответственных за отдельные части репозитория. Ответственными могут быть пользователи и группы. Изменения, затрагивающие файлы, указанные в CODEOWNERS, должны получить апрув от владельцев кода.
Использование CODEOWNERS помогает:
- требовать апрувы от доменных экспертов для важных директорий;
- упростить процесс поиска «ответственных» за конкретный участок кода.
CODEOWNERS дополняет механизм правил апрува, но не заменяет их. В отличие от правил апрува, которые задаются вручную в UI, CODEOWNERS работает через файл CODEOWNERS в репозитории.
Как работает CODEOWNERS
CODEOWNERS — текстовый файл в репозитории.
Deckhouse Code использует его для определения владельцев файлов, участвующих в запросе на слияние.
Ищется в трёх местах (по приоритету):
./CODEOWNERS../docs/CODEOWNERS../.gitlab/CODEOWNERS.
Используется только первый найденный файл.
Если в проекте существует несколько файлов и вы сейчас просматриваете неприоритетный, то увидите соответствующее сообщение.

Валидация файла CODEOWNERS
Валидация помогает увидеть ошибки в файле на этапе редактирования.
Если файл валиден, отображается соответствующее сообщение:

Если файл невалиден, будут отображены проблемные строки и тип ошибки:

Существует 4 вида ошибок валидации:
- У владельцев нет доступа в этот проект или их уровень доступа недостаточен — как минимум один из владельцев не имеет достаточных прав в проекте.
- Пробелы в пути — если путь содержит пробелы, нужно их экранировать символом
\. - Нет владельцев — не указано ни одного владельца.
- Незакрытый раздел — не хватает символа закрытия раздела
].
Где применяется CODEOWNERS
Если MR, изменяющий файл, попадает под правила CODEOWNERS, то необходимо получить апрувы от владельцев.
Формат CODEOWNERS
Строка правила:
<путь или паттерн> <список владельцев>
Владельцы:
@user;@group;@group/subgroup;- роли:
@@developer,@@maintainer,@@owner.
Примеры
# Владелец всех файлов
* @default-team
# README.md только в корне
/README.md @docs-team
# Все Ruby-файлы
*.rb @backend-team
# Вся директория config
/config/ @devops
# README.md в любом месте
README.md @docs
Паттерны путей
Deckhouse Code использует подстановочные символы:
*— любые символы кроме/.**— матч нескольких уровней директорий./dir/— только указанная директория.*.md— все Markdown-файлы./config/**/*.rb— все Ruby-файлы внутриconfig/*на всех уровнях.
Примеры паттернов
/docs/* @docs-one # один уровень
/docs/** @docs-two # рекурсивно
/app/**/*.rb @ruby-team
Секции CODEOWNERS
В файле CODEOWNERS секции — это именованные области, которые анализируются отдельно и всегда применяются. Пока вы не определите ни одной секции, Deckhouse Code рассматривает весь файл CODEOWNERS как одну единственную секцию.
Особенности использования CODEOWNERS:
- Deckhouse Code рассматривает записи без секций, включая правила, определённые до первой секции, как отдельную, безымянную секцию.
- Каждая секция обрабатывает свои правила отдельно.
- Если путь к файлу соответствует нескольким записям внутри одной секции, используется только последняя подходящая запись в этой секции.
- Если путь к файлу соответствует записям в нескольких секциях, используется последняя подходящая запись в каждой секции.
Например, в файле CODEOWNERS со следующими секциями, определяющими владельцев для README:
* @root
[README Owners]
README.md @user1 @user2
internal/README.md @user4
[README other owners]
README.md @user3
Владельцы для README.md в корневой директории:
@root— из безымянной секции.@user1и@user2— из секции[README Owners].@user3— из секции[README other owners].
Владельцы для internal/README.md:
@root— из безымянной секции.@user4— из секции[README Owners]. (ИREADME.md, иinternal/README.mdподходят под правила секции, но используется только последняя подходящая запись в этой секции).@user3— из секции[README other owners].
В виджете запроса на слияние каждый владелец кода отображается под своим ярлыком.

Детальный пример: сложная комбинация секций
Ниже — пример реального промышленного файла, показывающий:
- секции с разным количеством апрувов;
- переопределение владельцев;
- опциональные секции;
- исключения;
- наследование секций с одинаковыми именами.
# Глобальные настройки
* @fallback-team
!*.lock # lock-файлы не требуют апрувов
!**/generated/** # автоматическая генерация
[Backend][2] @backend-core
# Требуются 2 апрува от backend-core для любого Ruby-кода
app/**/*.rb
# Но для критических моделей определяем другой порядок
app/models/**/*.rb @backend-core @security-team
# А вот эта модель — исключение, владелец другой
app/models/legacy/**/*.rb @migration-team
[Backend]
# Дополнение секции: теперь Backend включает также SQL
db/**/*.sql @db-team
[Ruby Optional]
# Дополнительная подсветка владельцев, апрувы НЕ обязательны
^[Ruby Optional]
*.rb @ruby-advisors
[Frontend][3]
# Для UI требуется 3 апрува
*.vue @frontend-team
*.js @frontend-team
# переопределение: конкретный файл → конкретный человек
frontend/critical_entry.vue @frontend-lead
[Docs]
*.md @technical-writers
[Docs]
# переопределение: README всегда принадлежит docs-lead
README.md @docs-lead
Особенности примера:
- секция
[Backend]объявлена дважды → Deckhouse Code объединит её; [Backend][2] @backend-coreзадаёт обязательные 2 апрува;[Frontend][3]требует 3 апрува от фронтенда;[Ruby Optional]отмечена как опциональная — владельцы видны, но их апрув не обязателен;- исключения
!*.lockи!**/generated/**означают, что эти файлы вообще не требуют апрувов.
Исключения (!)
Используются для исключения файлов внутри секции:
* @default
!package-lock.json
!**/generated/**
После исключения файл не может быть снова включён в ту же секцию.
Порядок обработки правил
Правила обрабатываются в соответствии со следующим порядком:
- Deckhouse Code читает файл сверху вниз.
- В пределах одной секции правила с одинаковым путём переопределяют предыдущие.
- Если файл подходит под несколько секций — владельцы из всех этих секций добавляются.
- Секции не переопределяют друг друга — они независимы.
Кто может быть владельцем (eligible owners)
1. Пользователи (через @username)
Пользователь считается валидным владельцем, если:
- Имеет прямое членство в проекте (Developer, Maintainer или Owner).
- Имеет членство в группе проекта (включая наследуемое: группа проекта, родительские группы, предки родительских групп).
- Является прямым или унаследованным участником группы, которая напрямую приглашена в проект.
- Является прямым но не унаследованным участником группы которая приглашена в группу проекта.
- Является прямым но не унаследованным участником группы которая приглашена в предка группы проекта.
Если подытожить, то подходят все пользователи которые отображаются на странице участников проекта с ролью developer или выше.
Не считается владельцем, если:
- заблокирован,
- доступ отозван,
- роль ниже Developer.
2. Группы (через @group или @group/subgroup)
Группа может быть владельцем только если:
- Она напрямую приглашена в проект с ролью Developer+ (через “Пригласить группу”).
- Владельцами считаются только прямые участники этой группы.
Наследуемые участники родительских групп владельцами не считаются.
3. Роли (через @@role)
Формат:
@@developer
@@maintainer
@@owner
Особенности:
- учитываются только прямые участники проекта;
- члены групп в расчёт не входят;
- роли не наследуют друг друга (
@@developerНЕ включает maintainer’ов).
Можно указывать несколько ролей в одной строке:
file.md @@developer @@maintainer
Взаимодействие с правилами апрува
CODEOWNERS и правила апрувов работают независимо, но их требования суммируются.
Пример:
- правило
Securityтребует 1 апрув; - секция
[Backend][2]требует 2 апрува; - MR меняет backend-файл.
Итог: необходимо 3 апрува.
Рекомендации по оформлению
При оформлении файла CODEOWNERS следуйте рекомендациям:
- Сначала задавайте широкие правила (
* @team). Далее уточняющие (app/**/*.rb @backend-team). - Используйте секции для лучшей структуры и наглядности.
- Избегайте дубликатов — последнее правило в секции имеет приоритет.
- Опциональные секции полезны для подсветки экспертов без обязательных апрувов.
Пример финального файла
# Глобальные владельцы
* @default-team
# Исключения
!yarn.lock
!**/generated/**
[Backend][2]
app/**/*.rb @backend-core
[Frontend][3]
*.vue @frontend-team
*.js @frontend-team
^[Docs]
*.md @docs-team
[Critical Overrides]
/config/production.yml @ops-lead