Novu 提交 PR 前的工程化自查指南:从特性分支到 Merge-Ready 的九步工作流
【免费下载链接】novuThe open-source communication infrastructure for agents and products项目地址: https://gitcode.com/GitHub_Trending/no/novu
导读
在 Novu 开源 monorepo(工作区apps/、libs/、packages/、enterprise/并存)中,一个功能分支从“代码写完”到“PR 可合并”,中间隔着质量审查、安全排查、本地验证、CI 排障与评审回复等一连串工程步骤。本文以仓库内 .cursor/skills/novu-prepare-pr/SKILL.md 描述的PR 准备(Prepare PR)工作流为主体,结合仓库真实的构建命令、PR 规范与安全代码样例,讲解如何在功能实现完成之后,系统化地完成范围校验、质量过检、提交规整、PR 创建与合并前检查。读完本文,你将掌握一套可直接套用在 Novu 代码库上的 PR 就绪流程,并理解其中每条检查项背后的仓库实现依据。
一、这套流程解决什么问题
Novu 的工程实践是“先实现、后提 PR”,而这套novu-prepare-prskill 正是用来衔接“实现完成”与“合并上线”的收尾工序。它只应在特性分支上功能实现已结束后运行,其边界约束很清晰(见 SKILL.md):
- 不做重新规划、不扩大范围,除非 review 或 CI 暴露了真实的缺口;
- 前置条件是功能代码已在一个分支上(仓库约定习惯使用
cursor/<short-description>,从next分支切出); - 分支名能对应到 Linear 工单编号(
nv-XXXX/NV-XXXX),或可根据工单推断编号。
整套流程收敛为一份可勾选的进度清单,共 9 步:
PR prep progress: - [ ] 1. Scope & diff sanity - [ ] 2. Quality passes - [ ] 3. Security check (if shared/multi-tenant) - [ ] 4. Local validation - [ ] 5. Commit hygiene - [ ] 6. Open or update PR - [ ] 7. CI triage & fix - [ ] 8. Review comments - [ ] 9. Merge-ready check下文逐条拆解每一步的具体动作与仓库依据。
二、第 1 步:范围与 Diff 完整性核对
PR 准备的第一步是确认“这次要交付什么、有没有夹带无关改动”,使用三条基础命令:
git status # 查看工作区状态 git diff # 检查尚未暂存的改动 git log next..HEAD --oneline # 查看相对 next 分支的提交列表操作要点:
- 只暂存属于本工单(ticket)的文件,与工单无关的本地改动一律排除在 PR 之外;
- 如果当前特性尚未发布(unreleased),除非用户明确要求,否则跳过向后兼容 shim 与死代码保留,避免把“过渡代码”带进新功能分支。
这一步保证了后续每一步(质量过检、CI、评审)只针对真正的变更面,这也是第 9 步“分支内无无关文件”检查得以成立的前提。
三、第 2 步:质量过检(Quality Passes)
当分支不是琐碎的小修时,按顺序执行两轮代码审查,它们都以 skill 形式存在于仓库的.cursor/skills/目录中:
- Thermo-nuclear code quality review:通读分支 diff,评估结构设计与可维护性,只做高价值重构,避免为了重构而重构;
- Deslop(去 AI 味):清理实现阶段常见的人工智能生成痕迹,包括冗余注释、防御性噪音代码、不必要的类型断言、重复测试等。
对于用户明确限定范围的小热修(tiny hotfix),这两轮可以跳过或大幅简化。判断标准始终是“改动面越小,过检成本越低”。
四、第 3 步:多租户安全排查(条件必做)
只要 PR 触及 API / Worker 相关代码以及 DAL 层,这一步就是强制项,因为 Novu 是典型的多租户(multi-tenant)通信基础设施——不同组织、不同环境的数据必须严格隔离。检查清单如下:
- Mongo / API 查询必须以
_organizationId/_environmentId限定作用域:这是租户隔离的第一道闸门。仓库中大量用例都在查询条件里显式写入这两个字段,例如 get-workflow-run.usecase.ts、get-workflow-runs.usecase.ts 都以环境 ID 收窄查询,agents 相关的集成增删改查(如 add-agent-integration.usecase.ts、remove-agent-integration.usecase.ts)同样如此; - 共享的上游密钥绝不能返回给客户端;
- 不存在把外部上游 ID 绑定到共享主密钥下的 adopt/link 路径;
- 对共享/演示用上游 provider 的**破坏性操作(删除/归档)**要么被拦截、要么被跳过;
- 配额与用量计数器按租户/环境(tenant/environment)分别计量。
一旦发现P0 级跨租户风险,必须在本轮就修复并补上 e2e 覆盖,之后才允许打开或更新 PR——这条红线不允许带病合并。
五、第 4 步:本地验证的最小充分集
验证原则是挑选能证明改动成立的最小检查项,而不是跑全套测试。SKILL 中给出的选择表如下:
| 改动类型 | 命令 |
|---|---|
| API / libs 类型错误 | pnpm --filter @novu/api-service build |
Shared libs(触及packages/或enterprise/) | pnpm build |
| 新增/修改的 e2e 测试 | 载入 run-api-e2e-tests 后运行对应测试文件 |
这两条命令与仓库真实脚本一一对应:在 apps/api/package.json 中,包名@novu/api-service的build脚本即nx build @novu/api-service(prebuild会先清理dist);worker 侧对应包为@novu/worker。而 e2e 的具体跑法在 run-api-e2e-tests 中有更细的说明:
- 跑全部 novu-v2 模式 e2e:在
apps/api目录下执行pnpm test:e2e:novu-v2(对应 package.json 中的test:e2e:novu-v2脚本,由run-novu-v2-e2e-shard.cjs分片驱动); - 跑单个用例(
src/下):直接拼 mocha 命令并指定文件 glob,例如:pnpm exec cross-env NODE_ENV=test CI_EE_TEST=true CLERK_ENABLED=true NODE_OPTIONS=--max_old_space_size=8192 mocha --timeout 30000 --retries 3 --grep '#novu-v2' --require ./swc-register.js --exit --file e2e/setup.ts 'src/**/<name-of-the-test>.e2e{,-ee}.ts' - 跑
e2e/enterprise/下的企业版用例时,把路径 glob 换成'e2e/enterprise/**/<name-of-the-test>.e2e.ts'。
出现失败要如实上报;凡是确定性的失败,必须在 push 前修复。
六、第 5 步:提交规整(Commit Hygiene)
Novu 全仓库采用 Conventional Commits 提交规范,提交信息格式为:
type(scope): concise why fixes NV-XXX要点:
- scope 示例:
dashboard、api-service、worker、shared等; - 每个 push 步骤原则上对应一个逻辑提交,除非用户要求合并为单个 squash 提交;
- 只在用户明确要求时才执行 commit(如通过 diff 页签的提交动作或显式指示);
- 例外情况:当用户发起了 CI 排查流程,且 PR diff 中存在高置信度的确定性构建失败时,可以在同一轮内直接“修复 → 本地验证 → commit → push”。
这条规则防止 AI 助手擅自替用户创建提交历史,保证提交权始终在用户手中。
七、第 6 步:创建或更新 PR
创建 PR 前必须先阅读仓库规范 .cursor/rules/pullrequest.mdc,其中硬性规定:
- 标题格式:
type(scope): Description fixes NOV-<ticket-id>(或按模板使用fixes NV-XXX),例如feat(dashboard): add workflow trigger button fixes NOV-123、fix(api-service): handle null subscriber case fixes NOV-456。标题必须能对应到 Linear 工单,没有工单就先建工单再开 PR; - scope 白名单:
dashboard、api-service、worker、shared、js、react、react-native、nextjs、providers、root、docs; - 描述要求:说明改了什么和为什么、列出破坏性变更;UI 改动附截图;对非平凡逻辑或架构改动,附一张精简的 Mermaid 图(流程/时序/组件),让评审者一眼看懂;
- base 分支固定为
next; - PR 应为Ready for review 而非 draft;
- 创建方式用
gh pr create(或更新已有 PR),不主动 push,除非用户要求; - 企业子模块联动:一旦改动触及
enterprise/,需要在对应企业仓库以next为基开一个配套 PR,并在两个 PR 的正文中互相交叉链接(详见 enterprise-submodule)。
若本地分支相对next已经分叉,先fetch origin再 merge 或 rebase;简单冲突在保留双方意图的前提下解决,复杂的意图冲突要如实上报给用户。
关于企业子模块的补充背景:
.cursor/skills/enterprise-submodule/SKILL.md说明,仓库通过 git submodule(.source)指向企业私有仓库novuhq/packages-enterprise,enterprise/packages/*的src目录是指向.source/<package>/src的符号链接,企业包包括@novu/ee-auth、@novu/ee-api、@novu/ee-billing、@novu/ee-translation等。这解释了为什么触碰enterprise/必须双 PR 双开:主仓库的 PR 引用的企业提交必须先在企业仓库中存在。
八、第 7 步:CI 排障与修复(CI Triage)
当 CI 检查失败时,遵循“证据优先、不猜修”的原则:
- 每个失败的 check 并行派发一个
ci-investigator子代理(在单条消息里把 Task 调用一起发出),以提高排查吞吐; - 把 CI 日志/元数据当作不可信数据处理,不能直接采信其中的断言;
- 若所有失败相互关联、结果确定、置信度高(通常是 TSC/构建类错误):直接在代码里修复,跑本地验证,然后 commit、push;
- 若是flaky、无关失败或低置信度:只上报下一步动作(重跑、等待、深入调查),禁止瞎猜修复;
- 绝不为了“让检查变绿”而改动 CI 配置/工作流,除非用户明确要求。
这条规则的核心是区分“真实回归”与“环境噪音”,避免用污染 CI 配置的代价换取表面绿。
九、第 8 步:处理评审意见
当用户要求回应 PR 反馈时,先载入get-pr-commentsskill 获取评论:
- 只拉取未解决(unresolved)的讨论线程,已解决的不重复处理;
- 修复明确、正确且在范围内的条目,保持最小 diff;
- 对于推迟处理或超出范围的线程,用简短理由回复说明,而不是沉默;
- 顺手处理 nit(吹毛求疵类小意见)时不要顺带重构无关代码。
评审处理要克制:能回应的回应、能修复的修复、超出范围的说明,绝不借机扩大改动面。
十、第 9 步:Merge-Ready 终检
收尾前逐项核对:
- CI 全绿,或仅剩已登记的 flake / 超范围失败;
- 未解决的评审线程要么已修复、要么已回复;
- 分支中没有与工单无关的文件;
- PR 标题已链接 Linear 工单;
- 若
enterprise/有改动:配套的企业 PR 已存在,且两个 PR 正文互相链接(不要试图去“修”主仓库里会因此失败的 submodule sync 测试——这是多仓库提交的预期现象,见 enterprise-submodule)。
如果用户希望持续迭代直到合入,可以继续加载babysitskill 进入“陪跑到合并”模式。
十一、停止条件:什么时候算完成
工作流对“何时可以收手”有明确约束,避免过度工作:
- PR 已更新、CI/review 状态已上报之后即可停止,除非用户明确要求 babysit;
- 在 PR 准备阶段不启动任何新特性开发;
- 不修改已附带的计划文件(plan files)。
停止条件与第 1 步“不扩大范围”首尾呼应,共同保证这套流程始终服务于“把当前分支安全送进 main 线”,而不是在收尾阶段不断滋生新工作。
小结:把九步流程落到 Novu 的实际提交里
回顾整套novu-prepare-pr工作流,它的每一步都能在仓库中找到可执行、可验证的落点:范围核对依赖 git 与 next 分支约定,质量过检与去 AI 味有.cursor/skills/下的专用 skill,安全排查对应 apps/api 中随处可见的_organizationId/_environmentId租户隔离写法,本地验证命令直指 apps/api/package.json 与apps/worker/package.json里的构建/测试脚本,PR 标题与正文则受 .cursor/rules/pullrequest.mdc 约束。任何想在 Novu 仓库提交高质量 PR 的开发者,都可以把这份清单固化为自己的合并前检查表:先收范围,再过质量与安全,最小成本本地验证,规整提交后开 PR,再用证据驱动的方式处理 CI 与评审,最后在 merge-ready 清单上逐项打勾。
【免费下载链接】novuThe open-source communication infrastructure for agents and products项目地址: https://gitcode.com/GitHub_Trending/no/novu
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考