审批规则开发指南
本文档解释了所有相关功能的后端设计和流程,包括合并请求审批规则。
这应该能帮助贡献者更容易地理解代码设计,并随着功能及其实现的演进,帮助识别是否有需要改进的部分。
本文档有意不包含太多实现细节,因为它们可能会经常变化。代码应该能更好地解释这些内容。这里提到的组件是审批规则功能正常工作的主要部分。
这是一份动态文档,当本文档中涉及的代码库部分被更改或移除,或者添加了新组件时,应相应更新。
数据模型
%%{init: { "fontFamily": "GitLab Sans" }}%%
erDiagram
accTitle: Approval rules data model
accDescr: Entity relationship diagram of approval rules
Project ||--o{ MergeRequest: " "
Project ||--o{ ApprovalProjectRule: " "
ApprovalProjectRule }o--o{ User: " "
ApprovalProjectRule }o--o{ Group: " "
ApprovalProjectRule }o--o{ ProtectedBranch: " "
MergeRequest ||--|| ApprovalState: " "
ApprovalState ||--o{ ApprovalWrappedRule: " "
MergeRequest ||--o{ Approval: " "
MergeRequest ||--o{ ApprovalMergeRequestRule: " "
ApprovalMergeRequestRule }o--o{ User: " "
ApprovalMergeRequestRule }o--o{ Group: " "
ApprovalMergeRequestRule ||--o| ApprovalProjectRule: " "
Project 和 MergeRequest
Project 和 MergeRequest 模型定义在 ee/app/models/ee/project.rb 和 ee/app/models/ee/merge_request.rb 中。它们扩展了非 EE 版本,因为审批规则是 EE 专属功能。与合并请求审批相关的关联和其他内容在此定义。
ApprovalState
%%{init: { "fontFamily": "GitLab Sans" }}%%
erDiagram
accTitle: ApprovalState
accDescr: Entity relationship diagram between MergeRequest and ApprovalState
MergeRequest ||--|| ApprovalState: " "
ApprovalState 类定义在 ee/app/models/approval_state.rb 中。它不是一个实际的 ActiveRecord 模型。这个类封装了与特定合并请求审批状态相关的所有逻辑,例如:
- 根据目标分支了解适用于合并请求的审批规则。
- 了解适用于特定目标分支的审批规则。
- 检查所有规则是否已批准。
- 检查是否需要审批。
- 了解已给出或仍需的审批数量。
它从项目(ApprovalProjectRule)或合并请求(ApprovalMergeRequestRule)获取审批规则数据,并将其包装为 ApprovalWrappedRule。
ApprovalProjectRule
%%{init: { "fontFamily": "GitLab Sans" }}%%
erDiagram
accTitle: ApprovalProjectRule diagram
accDescr: Entity relationship diagram between projects and ApprovalProjectRule
Project ||--o{ ApprovalProjectRule: " "
ApprovalProjectRule }o--o{ User: " "
ApprovalProjectRule }o--o{ Group: " "
ApprovalProjectRule }o--o{ ProtectedBranch: " "
ApprovalProjectRule 模型定义在 ee/app/models/approval_project_rule.rb 中。
当通过项目设置或项目审批规则 API添加/编辑/移除审批规则时,会创建/更新/删除记录。当审批规则未被覆盖时,ApprovalState 模型会获取这些记录。
当规则限定于受保护分支时,会设置和使用 protected_branches 属性。有关该功能的更多信息,请参阅受保护分支的审批。
ApprovalMergeRequestRule
%%{init: { "fontFamily": "GitLab Sans" }}%%
erDiagram
accTitle: ApprovalMergeRequestRule diagram
accDescr: Entity relationship diagram between MergeRequest and ApprovalMergeRequestRule
MergeRequest ||--o{ ApprovalMergeRequestRule: " "
ApprovalMergeRequestRule }o--o{ User: " "
ApprovalMergeRequestRule }o--o{ Group: " "
ApprovalMergeRequestRule ||--o| ApprovalProjectRule: " "
ApprovalMergeRequestRule 模型定义在 ee/app/models/approval_merge_request_rule.rb 中。
当通过合并请求创建/编辑表单或单个合并请求审批 API添加/编辑/移除规则时,会创建/更新/删除记录。
当基于现有的 ApprovalProjectRule 时,会设置 approval_project_rule。
ApprovalMergeRequestRule 没有 protected_branches,因为它从 approval_project_rule 继承这些属性(除非被覆盖)。
ApprovalWrappedRule
%%{init: { "fontFamily": "GitLab Sans" }}%%
erDiagram
accTitle: ApprovalWrappedRule diagram
accDescr: Entity relationship diagram between ApprovalState and ApprovalWrappedRule
ApprovalState ||--o{ ApprovalWrappedRule: " "
ApprovalWrappedRule 定义在 ee/app/modes/approval_wrapped_rule.rb 中,不是一个 ActiveRecord 模型。它用于包装 ApprovalProjectRule 或 ApprovalMergeRequestRule 以提供通用接口。它还具有以下子类型:
ApprovalWrappedAnyApprovalRule- 用于包装any_approver规则。ApprovalWrappedCodeOwnerRule- 用于包装code_owner规则。
这个类将大部分职责委托给它包装的审批规则,但也负责:
- 检查审批规则是否已批准。
- 了解审批规则已给出或仍需的审批数量。
它从审批规则和合并请求的 Approval 记录中获取这些信息。
Approval
%%{init: { "fontFamily": "GitLab Sans" }}%%
erDiagram
accTitle: Approval diagram
accDescr: Entity relationship diagram between MergeRequest and Approval
MergeRequest ||--o{ Approval: " "
Approval 模型定义在 ee/app/models/approval.rb 中。该模型负责存储在合并请求上进行的审批信息。每当给出/撤销审批时,会创建/删除记录。
控制器和服务
以下控制器和服务用于使审批规则功能正常工作。
API::ProjectApprovalSettings
这个私有 API 定义在 ee/lib/api/project_approval_settings.rb 中。
用于以下用途:
- 列出项目设置中的审批规则。
- 在项目设置中创建/更新/删除规则。
- 在创建合并请求表单中列出审批规则。
Projects::MergeRequests::CreationsController
这个控制器定义在 app/controllers/projects/merge_requests/creations_controller.rb 中。
当提交创建合并请求表单时,会使用此控制器的 create 操作。它接受 approval_rules_attributes 参数来创建/更新/删除 ApprovalMergeRequestRule 记录。在执行 MergeRequests::CreateService 时,它会传递该参数。
Projects::MergeRequestsController
这个控制器定义在 app/controllers/projects/merge_requests_controller.rb 中。
当提交编辑合并请求表单时,会使用此控制器的 update 操作。它类似于 Projects::MergeRequests::CreationsController,但执行的是 MergeRequests::UpdateService。
API::MergeRequestApprovals
这个 API 定义在 ee/lib/api/merge_request_approvals.rb 中。
当合并请求页面加载时,会请求审批 API 端点。
/projects/:id/merge_requests/:merge_request_iid/approval_settings 是一个私有 API 端点,用于以下用途:
- 在编辑合并请求表单中列出审批规则。
- 在合并请求页面上列出审批规则。
当通过 UI 和 API 批准/取消批准 MR 时,会请求批准合并请求 API 端点或取消批准合并请求 API 端点。它们分别执行 MergeRequests::ApprovalService 和 MergeRequests::RemoveApprovalService。
API::ProjectApprovalRules 和 API::MergeRequestApprovalRules
这些 API 定义在 ee/lib/api/project_approval_rules.rb 和 ee/lib/api/merge_request_approval_rules.rb 中。
用于通过合并请求审批 API列出/创建/更新/删除项目和合并请求级别的规则。
分别执行 ApprovalRules::CreateService、ApprovalRules::UpdateService、ApprovalRules::ProjectRuleDestroyService 和 ApprovalRules::MergeRequestRuleDestroyService。
ApprovalRules::ParamsFilteringService
这个服务定义在 ee/app/services/approval_rules/params_filtering_service.rb 中。
它仅在执行 MergeRequests::CreateService 和 MergeRequests::UpdateService 时被调用。
它负责解析 approval_rules_attributes 参数,以:
- 当用户无法更新审批规则时移除它。
- 过滤用户 ID,检查他们是否是项目成员。
- 过滤组 ID,检查它们对用户是否可见。
- 识别
any_approver规则。 - 当指定时附加隐藏组。
- 添加用户定义的不适用(不适用于合并请求目标分支)的审批规则。
ApprovalRules::CreateService
这个服务定义在 ee/app/services/approval_rules/create_service.rb 中。
负责在合并请求或项目级别创建审批规则。
它在以下情况下被调用:
- 通过 UI 为项目创建审批规则。
- 通过 API::ProjectApprovalRules
/projects/:id/approval_rules端点为项目创建审批规则。 - 通过 API::MergeRequestApprovalRules
/projects/:id/merge_requests/:merge_request_iid/approval_rules端点为单个合并请求创建审批规则。
通过 UI 创建的合并请求审批规则不使用此服务。请参阅 Projects::MergeRequests::CreationsController
流程
这些流程图应该有助于解释从控制器到模型的不同功能流程。
一些 CRUD API 端点被有意跳过,因为它们相当直接。
通过 Web UI 创建带有审批规则的合并请求
%%{init: { "fontFamily": "GitLab Sans" }}%%
graph LR
accTitle: Merge request creation in the UI
accDescr: Flowchart of the creation of a merge request in the web UI, when the merge request contains approval rules
Projects::MergeRequests::CreationsController --> MergeRequests::CreateService
MergeRequests::CreateService --> ApprovalRules::ParamsFilteringService
ApprovalRules::ParamsFilteringService --> MergeRequests::CreateService
MergeRequests::CreateService --> MergeRequest
MergeRequest --> db[(Database)]
MergeRequest --> User
MergeRequest --> Group
MergeRequest --> ApprovalProjectRule
User --> db[(Database)]
Group --> db[(Database)]
ApprovalProjectRule --> db[(Database)]
更新时遵循相同的流程,但始于 Projects::MergeRequestsController 并执行 MergeRequests::UpdateService。
在 MR 页面上查看合并请求审批规则
%%{init: { "fontFamily": "GitLab Sans" }}%%
graph LR
accTitle: Viewing approval rules on a merge request
accDescr: Flowchart of how the frontend retrieves, then displays, approval rule information on a merge request page
API::MergeRequestApprovals --> MergeRequest
MergeRequest --> ApprovalState
ApprovalState --> id1{approval rules are overridden}
id1{approval rules are overridden} --> |No| ApprovalProjectRule & ApprovalMergeRequestRule
id1{approval rules are overridden} --> |Yes| ApprovalMergeRequestRule
ApprovalState --> ApprovalWrappedRule
ApprovalWrappedRule --> Approval
此流程由前端组件启动。返回的数据用于在 MR 小部件上显示信息。
批准合并请求
%%{init: { "fontFamily": "GitLab Sans" }}%%
graph LR
accTitle: Approval data flowchart
accDescr: Flowchart of how an approval call to the API reaches the database
API::MergeRequestApprovals --> MergeRequests::ApprovalService
MergeRequests::ApprovalService --> Approval
Approval --> db[(Database)]
取消批准时遵循相同的流程,但执行的是 MergeRequests::RemoveApprovalService。
TODO
- 添加与其他规则类型相关的信息,例如
code_owner和report_approver。 - 添加关于批准/取消批准合并请求的副作用信息。