你在周五下午四点推送了一个修复。到了周六早上,警报声大作。你追踪到这次事故源于 18 小时前合并的一个 pull request。分支编译通过了,测试也通过了,但 PR 描述是空的。没有任何工作项与之关联。审批历史也显示为空白。你面对的是一个“幽灵合并”,现在你不得不利用整个周末来清理这场本该在触及 main 分支之前就被拦截的烂摊子。
小团队每天都面临这种风险。你没有发布经理盯着每一次合并,也没有平台团队来构建定制化的策略引擎。你只有 Azure DevOps,而它内置的分支策略就像一种粗糙的工具。它们要么把门关死,要么大开着。要求两个评审人会阻碍紧急热修复;放宽规则,空洞的描述就会随着未关联工单的变更一起进入生产环境。两者之间很少有中间地带。
这种差距正是我们构建 Gatekeeper 的原因。它是一个专为 Azure DevOps 设计的 AI 驱动型 PR 评审台,但请忘掉你对现代开发工具的所有固有认知。这里没有 Docker 容器,没有订阅计划,也没有云端部署流水线。Gatekeeper 只是一个单一的 HTML 文件。你在浏览器中打开它,输入四个数值,然后点击按钮。随后,该工具会回答三个简单的问题:这个 PR 是否关联了工单?是否真的有人进行了人工评审?代码质量如何?
将所有内容打包成一个自包含文件的决定并非噱头,它解决了实际的运维难题。首先,无需托管或支付任何基础设施费用。你不需要配置 App Service,也不必担心出站流量成本。其次,凭据永远不会离开你的机器。你的 Azure DevOps 个人访问令牌(personal access token)仅存在于浏览器内存中,一旦刷新页面就会消失。没有可能泄露的密钥数据库,也不需要信任任何 OAuth 服务器。第三,采用过程变得毫无阻碍。你不需要通过 Wiki 来引导任何人。你可以将文件随邮件发送,或者直接丢进 Slack 频道。接收者打开它即可立即开始评审。
事实层:确定性优先
Gatekeeper 将其评审分为两个截然不同的层级,这种分离是其可靠性的支柱。
第一层是直接与 Azure DevOps REST API 通信的纯 JavaScript。它检查那些不会改变的事实。一个 pull request 要么关联了工作项,要么没有;评审人要么投了赞成票,要么没有;描述要么是空的,要么包含实际的句子;活跃的讨论要么已解决,要么仍处于开启状态。
具体而言,事实层会检查四件事:
- 工单映射: PR 是否至少关联了一个工作项?
- 评审人签核: 是否有人投票批准,还是计数仍为零?
- 描述质量: 描述是空的,还是仅仅是一个简陋的占位符?
- 未解决的讨论: 是否存在等待回复的未解决评论线程?
这些检查会在页面上生成视觉印章。一个醒目的红色 NOT MAPPED 印章很难被忽视。而藏在表格单元格里的细小绿色勾选标记则很容易被漏掉。我们很早就意识到,流程失效需要“大声疾呼”。当开发人员急于合并时,含蓄是行不通的。事实层的存在就是为了彻底消除歧义。
由于这一层依赖于确定性的 API 响应,其准确性是绝对的。如果印章显示 NO APPROVAL,你可以断定没有人点击过批准按钮。如果显示 UNRESOLVED THREADS,则说明对话仍在进行中。这一层并不会
