跳到内容
BeeuniBeeuni
中文
Esc
↑↓导航↵打开⌘J预览
本页内容

更改请求

会话工作如何通过评审进入默认分支。

更改请求(CR)会将一个 git 分支合并到另一个分支。Beeuni 会将会话分支(head_ref)上的更改创建为 CR,目标是项目的默认分支(base_ref,通常为 main)。CR 行是元数据;合并、差异和冲突检查会针对项目仓库作为真实的 git 操作运行。CR 是会话工作进入默认分支的唯一途径。

为什么工作要经过 CR

会话在沙箱中运行,并使用以会话 ID 命名的独立分支。沙箱不会永久存在,但分支会保留:git 是会话工作唯一持久的记录。每个新会话都从默认分支开始。在 CR 完成合并之前,工作会留在自己的分支上,未经审查,其他代理、触发器和协作者都不可见。这适用于所有更改:代码、代理、技能和清单(beeuni.yaml)——没有例外。

代理必须遵守的要求

代理必须打开 CR,才能将任何更改落到项目的默认分支上。代理不得合并自己的 CR——合并由用户决定。请遵循以下约定:

  1. 在会话分支($BEEUNI_BRANCH_NAME)上提交。使用小型、可工作的提交。不要重写历史记录或强制推送。
  2. 推送分支:git push origin HEAD。
  3. 打开 CR:beeuni cr open --title "..." --description "..."。在会话沙箱中,--head 和 --session 默认为 $BEEUNI_BRANCH_NAME 和 $BEEUNI_SESSION_ID。--base 默认为项目的默认分支。
  4. 告知用户 CR 编号,以便用户审查。
  5. 停止操作。不要自行合并 CR。

反模式

  • 强制推送到默认分支。 即使后端允许,这也会破坏审查约定。
  • “代码在我的分支上,你自己拉取吧。” 沙箱停止后,会话分支就会消失,除非 CR 已先将其合并。
  • 通过文件、粘贴内容或存档发送更改。 CR 系统已经解决了这个问题。

数据模型

CR 存储在 change_requests 表中。

列 类型 说明
cr_id uuid 主键。REST API 的标识符。
project_id uuid CR 所属的项目。
number integer 每个项目的显示编号(#1、#2……)。在项目内唯一。不会重新使用。
title text 必填。
description text 默认为空字符串。
base_ref text 被合并到的分支。通常为 main。
head_ref text 被合并的来源分支。在会话中,这是会话 ID(UUID)。
status enum open、merged 或 closed。
head_commit_sha text 对于打开的 CR,每次读取时都会根据实时 head_ref 最新提交刷新。对于已合并的 CR,在合并时记录。
base_commit_sha text base_ref 采用相同规则。
origin_session_id text 打开 CR 的会话。如果该会话被删除,则设为 null。
created_by uuid 创建 CR 的用户。
merged_at / merged_by timestamp / uuid 合并 CR 的时间和用户。
merge_commit_sha text 合并提交。快速前进时等于 head_commit_sha。
closed_at / closed_by timestamp / uuid 不合并而关闭 CR 的时间和用户。
metadata jsonb 包含 requested_changes,即由 POST /:crId/request-changes 添加的 {text, by, at} 条目列表。CR 没有单独的评论表。
created_at / updated_at timestamp 创建时设置。在每次状态更改或 SHA 刷新时更新。

(project_id, number) 上的唯一索引允许你通过短编号而不是 UUID 引用 CR。

生命周期

open ──(merge)──▶ merged      (terminal)
open ──(close)──▶ closed ──(reopen)──▶ open
  • open 是初始状态。
  • closed 可以撤销。POST /:crId/reopen 会将其设回 open。
  • merged 是终止状态。无法重新打开或关闭已合并的 CR。请针对已合并状态打开新的 CR。

如果某个分支没有领先默认分支的提交,Beeuni 会拒绝创建该分支的 CR。这通常意味着代理已在本地提交,但从未推送。请推送提交,然后重新创建 CR。

SHA 刷新

对于打开的 CR,Beeuni 会在每次 GET 时,根据实时分支刷新 head_commit_sha 和 base_commit_sha。如果仓库无法访问,或某个分支不存在,Beeuni 会跳过刷新,并提供 CR 最后已知的元数据。已合并的 CR 会保留合并时记录的 SHA——Beeuni 不会再次刷新它们。

合并机制

POST /v1/projects/:projectId/change-requests/:crId/merge 会执行以下步骤。

  1. Beeuni 从 head_ref 读取清单(beeuni.yaml),并根据清单架构进行验证。没有清单的分支可以通过验证。无效清单会返回带有 code: "MANIFEST_INVALID" 的 422,并停止合并。
  2. 如果 head_ref 严格领先于 base_ref,Beeuni 会将 该分支 快速前进。
  3. 否则,Beeuni 会创建合并提交。默认消息为 Merge CR #<n>: <title>,也可以在请求正文中通过 message 覆盖。提交作者为 Beeuni <noreply@beeuni.com>。
  4. 发生冲突时,会返回带有冲突列表的 409。合并前可通过 GET /:crId/merge-preview 检查相同列表。
  5. 成功后,Beeuni 会将 status 设置为 merged,记录 merged_at、merged_by 和 merge_commit_sha,并使项目的 git 缓存失效。

合并状态不是 open 的 CR 会返回 409。

合并预览

GET /:crId/merge-preview 会返回:

字段 类型 含义
base_sha string base_ref 的当前最新提交。
head_sha string head_ref 的当前最新提交。
merge_base string | null 共同祖先。如果历史记录不相关,则为 Null。
is_up_to_date boolean head_ref 已完全合并到 base_ref。
can_merge boolean 没有冲突。
can_fast_forward boolean head_ref 严格领先于 base_ref。
conflicts string[] 将发生冲突的文件路径。

REST API

所有路由都位于 /v1/projects/:projectId/change-requests 下。

方法 路径 说明
GET / ?status=open|merged|closed|all。不提供筛选条件时返回所有状态。
POST / 正文:{title, description?, head_ref, base_ref?, session_id?}。返回 201。
GET /:crId 返回 CR。会作为副作用刷新 SHA。
PATCH /:crId 编辑 title 或 description。如果不是 open,则 409。
GET /:crId/diff 统一补丁:文件列表、添加内容和删除内容。
GET /:crId/merge-preview 请参阅上面的“合并预览”。
POST /:crId/merge 正文:{message?}。清单无效时返回 422。发生冲突或不是 open 时返回 409。
POST /:crId/close 如果已经 merged,则 409。
POST /:crId/reopen 如果不是 closed,则 409。
POST /:crId/request-changes 正文:{feedback}。追加到 metadata.requested_changes,并唤醒发起会话的代理。如果不是 open,则 409。

POST / 会拒绝创建没有领先 base_ref 的提交的 head_ref:422 code: "CR_HEAD_NOT_AHEAD"。这是代理在推送分支之前打开 CR 时看到的错误。

授权

读取路由需要项目的读取权限。写入路由需要写入权限。每个写入操作还需要相应的能力,下面分别列出完整令牌和会话范围令牌所需的能力。

操作 能力
打开 CR project.gitops.push
请求更改 project.review.act
合并 project.gitops.merge

每项操作对应一项能力,无论是完整令牌还是权限范围受限的会话令牌。创建和合并是两个独立的叶子权限,因此令牌可以创建变更请求,却没有合并权限——这正是上文代理授权机制的实现方式。

project.cr.open 和 project.cr.merge 是切换前 project.gitops.push 和 project.gitops.merge 的名称——同一项能力的另一种名称。仍列出其中一个名称的 beeuni.yaml 仍然有效(解析时,授权会被改写为当前使用的名称),但新内容请使用 gitops 名称。

无论获得了什么授权,会话都不能合并自己创建的变更请求。这条规则是结构性的,并非一项能力。

这个页面有帮助吗?