Help us learn about your current experience with the documentation. Take the survey.

代码所有者开发指南

本文档旨在帮助贡献者理解 Code Owners 的代码设计。在为此功能修改代码前,您应该阅读本文档。

本文档有意仅概述代码的设计方式,因为代码经常变化。要了解功能特定部分的工作原理,请查看代码和规范。这里的细节解释了 Code Owners 功能主要组件的工作原理。

当本文档引用的代码库部分被更新、移除或添加新部分时,应更新本文档。

业务逻辑

代码所有者的所有业务逻辑都位于 Gitlab::CodeOwners 命名空间中。Code Owners 是一个仅 EE 版本的功能,因此文件仅存在于 ./ee 目录中。

  • Gitlab::CodeOwners: 用于与代码所有者规则交互的主模块。
    • 定义在 ./ee/lib/gitlab/code_owners.rb 中。
  • Gitlab::CodeOwners::File: 包装一个 CODEOWNERS 文件,并通过类的公共方法暴露数据。
    • 定义在 ./ee/lib/gitlab/code_owners/file.rb 中。
  • Gitlab::CodeOwners::Section: 包装 CODEOWNERS 文件中的节标题,并解析不同部分。
    • 定义在 ./ee/lib/gitlab/code_owners/section.rb 中。
  • Gitlab::CodeOwners::Entry: 包装 CODEOWNERS 文件中的一个条目(模式与所有者行),并通过类的公共方法暴露数据。
    • 定义在 ./ee/lib/gitlab/code_owners/entry.rb 中。
  • Gitlab::CodeOwners::Loader: 查找正确的 CODEOWNER 文件,并将内容加载到 Gitlab::CodeOwners::File 实例中。
    • 定义在 ./ee/lib/gitlab/code_owners/loader.rb 中。
  • Gitlab::CodeOwners::ReferenceExtractor: 从文本中提取 CODEOWNER 用户、组和邮件引用。
    • 定义在 ./ee/lib/gitlab/code_owners/reference_extractor.rb 中。
  • Gitlab::CodeOwners::UsersLoader: 查找正确的 CODEOWNER 文件,并将内容加载到 Gitlab::CodeOwners::File 实例中。
    • 定义在 ./ee/lib/gitlab/code_owners/users_loader.rb 中。
  • Gitlab::CodeOwners::GroupsLoader: 查找正确的 CODEOWNER 文件,并将内容加载到 Gitlab::CodeOwners::File 实例中。
    • 定义在 ./ee/lib/gitlab/code_owners/groups_loader.rb 中。
  • Gitlab::Checks::Diffs::CodeOwnersCheck: 当用户推送到启用了 require_code_owner_approval 的受保护分支时,验证 CODEOWNERS 条目中的文件是否未被更改。
    • 定义在 ./ee/lib/gitlab/checks/diffs/code_owners_check.rb 中。

代码所有者在 Git 访问检查执行顺序中的位置

Gitlab::Checks::DiffCheck#file_paths_validations 返回一个空数组,或者如果启用了 LFS 且存在文件锁,则返回一个包含 #lfs_file_locks_validation 结果单个成员的数组。此文件 EE 版本中 #validate_code_owners 的返回结果被插入到 EE::Gitlab::Checks::DiffCheck#file_paths_validations 列表的末尾。LFS 检查在 Code Owners 检查之前执行。

这些检查在 #validations_for_path 中列出的检查之后执行,后者仅存在于 EE 版本中,包括 #path_locks_validation#file_name_validation。这意味着在流程中,路径锁检查先于代码所有者检查。

EE 中的检查顺序如下(只有 LFS 作为非 EE 功能存在):

  • 路径锁
  • 文件名
    • 阻止包含密钥的文件,例如 id_rsa
    • 阻止匹配 PushRule#file_name_regex 的文件
  • LFS 文件锁
  • 代码所有者

相关模型

ProtectedBranch

ProtectedBranch 模型定义在 app/models/protected_branch.rb 中,并在 ee/app/models/concerns/ee/protected_branch.rb 中扩展。EE 版本包含一个名为 require_code_owner_approval 的列,如果文件列在 CODEOWNERS 中,则阻止更改直接推送到受保护的分支。

ApprovalMergeRequestRule

ApprovalMergeRequestRule 模型定义在 ee/app/models/approval_merge_request_rule.rb 中。 该模型存储合并请求的批准规则。我们使用多种规则类型,包括 code_owner 类型的规则。

控制器和服务

以下控制器和服务用于使批准规则功能正常工作:

Api::Internal::Base

当推送到 GitLab 时,会调用此 /internal/allowed 端点以确保用户被允许推送。/internal/allowed 端点执行 Gitlab::Checks::DiffCheck。在 EE 中,这包括代码所有者检查。

定义在 lib/api/internal/base.rb 中。

Repositories::GitHttpController

当通过 HTTP 将更改推送到 GitLab 时,控制器执行访问检查以确保用户被允许推送。检查执行 Gitlab::Checks::DiffCheck。在 EE 中,这包括 Code Owner 检查。

定义在 app/controllers/repositories/git_http_controller.rb 中。

EE::Gitlab::Checks::DiffCheck

此模块扩展了 CE Gitlab::Checks::DiffChecks 类并添加了代码所有者验证。它使用 Gitlab::Checks::Diffs::CodeOwnersCheck 类来验证用户是否没有将列在 CODEOWNER 中的文件直接推送到需要代码所有者批准的受保护分支。

MergeRequests::SyncCodeOwnerApprovalRules

此服务定义在 services/merge_requests/sync_code_owner_approval_rules.rb 中,用于:

  • 当新更改推送到合并请求时,删除过时的代码所有者批准规则。
  • 为合并请求中每个已更改的文件创建代码所有者批准规则,这些文件也列在 CODEOWNER 文件中。

流程

这些流程图应该有助于解释从控制器到不同功能模型的流程。

许多 Code Owners 实现存在于类的 EE 变体中。

通过 SSH 推送更改到启用了 require_code_owner_approval 的受保护分支

%%{init: { "fontFamily": "GitLab Sans" }}%%
graph TD
  Api::Internal::Base --> Gitlab::GitAccess
  Gitlab::GitAccess --> Gitlab::Checks::DiffCheck
  Gitlab::Checks::DiffCheck --> Gitlab::Checks::Diffs::CodeOwnersCheck
  Gitlab::Checks::Diffs::CodeOwnersCheck --> ProtectedBranch
  Gitlab::Checks::Diffs::CodeOwnersCheck --> Gitlab::CodeOwners::Loader
  Gitlab::CodeOwners::Loader --> Gitlab::CodeOwners::Entry

通过 HTTPS 推送更改到启用了 require_code_owner_approval 的受保护分支

%%{init: { "fontFamily": "GitLab Sans" }}%%
graph TD
  Repositories::GitHttpController --> Gitlab::GlRepository
  Gitlab::GlRepository --> Gitlab::GitAccessProject
  Gitlab::GitAccessProject --> Gitlab::Checks::DiffCheck
  Gitlab::Checks::DiffCheck --> Gitlab::Checks::Diffs::CodeOwnersCheck
  Gitlab::Checks::Diffs::CodeOwnersCheck --> ProtectedBranch
  Gitlab::Checks::Diffs::CodeOwnersCheck --> Gitlab::CodeOwners::Loader
  Gitlab::CodeOwners::Loader --> Gitlab::CodeOwners::Entry

将代码所有者规则同步到合并请求批准规则

%%{init: { "fontFamily": "GitLab Sans" }}%%
graph TD
  EE::ProtectedBranches::CreateService --> MergeRequest::SyncCodeOwnerApprovalRules
  EE::MergeRequestRefreshService --> MergeRequest::SyncCodeOwnerApprovalRules
  EE::MergeRequests::ReloadMergeHeadDiffService --> MergeRequest::SyncCodeOwnerApprovalRules
  EE::MergeRequests::CreateService --> MergeRequests::SyncCodeOwnerApprovalRulesWorker
  EE::MergeRequests::UpdateService --> MergeRequests::SyncCodeOwnerApprovalRulesWorker
  MergeRequests::SyncCodeOwnerApprovalRulesWorker --> MergeRequest::SyncCodeOwnerApprovalRules
  MergeRequest::SyncCodeOwnerApprovalRules --> id1{delete outdated code owner rules}
  MergeRequest::SyncCodeOwnerApprovalRules --> id2{create rule for each code owner entry}