Handsontable Monorepo Pull Request 全流程指南:从分支命名、预检到 Changelog 与合并
Handsontable Monorepo Pull Request 全流程指南从分支命名、预检到 Changelog 与合并【免费下载链接】handsontableJavaScript Data Grid / Data Table with a Spreadsheet Look Feel. Works with React, Angular, and Vue. Supported by the Handsontable team ⚡项目地址: https://gitcode.com/gh_mirrors/ha/handsontable本篇技术指南基于 Handsontable 仓库内建的开源工程规范完整讲解在该 monorepo 中创建高质量 Pull Request 的端到端工作流如何规范命名分支、执行预检命令、按模板填写 PR 描述、遵循先建 PR 再写 Changelog的顺序、启用 MANUAL QA 人工验收门禁以及最终通过 Squash and merge 合入 develop 分支。读完本文你将掌握一套可复制、可被 CI 机器校验的 PR 提交流程并理解每条规则背后的源码级依据。1. 分支命名规范前缀、任务 ID 与链接语义分支名是 PR 的第一张脸也是 ClickUp 与 GitHub 自动关联的载体。仓库规范要求根据工作类型选择前缀类型模式示例功能ClickUp默认feature/TASK-ID_Short-Descriptionfeature/DEV-627_Forum-Update文档ClickUpdocs/TASK-ID_Short-Descriptiondocs/DEV-458_Clarify-undo-redo-docs功能公开 GitHub issuefeature/issue-xxxxfeature/issue-11832文档公开 GitHub issuedocs/issue-xxxxdocs/issue-9500发布release/x.y.zrelease/16.1.0关键细节TASK-ID是 ClickUp 的 human-readable custom ID如DEV-627、IT-42前缀跟随任务所在的空间不一定是DEV。例如docs/SU-833_BeforeKeyDown-Return-False-Note、feature/PRO-858_Theme-API-e2e-test-data-driven-for-each-theme都是合法分支名。前缀必须从任务复制不要臆测。不要使用 ClickUp 的内部 hash ID如86c9j4fxj——它不是合法的任务标识符无法触发自动关联。创建任务后必须回读 custom IDclickup_create_task返回的custom_id是null正确流程是先调用clickup_get_task(task_id)拿到真实 custom ID再拼分支名1. clickup_create_task → 返回 task_idhash如 86c9j4fxj 2. clickup_get_task(task_id) → 返回 custom_id如 DEV-1532 3. 用 custom_id 命名分支feature/DEV-1532_Short-Description2. 预检检查开 PR 之前必须全绿推送分支前先在handsontable子包内运行以下检查任何失败都必须先修复# Lint npm run eslint --prefix handsontable npm run stylelint --prefix handsontable # Buildwrapper 依赖该产物 npm run build --prefix handsontable # 变更区域的单元测试 npm run test:unit --prefix handsontable --testPathPatternregex # 变更区域的 E2E 测试 npm run test:e2e --prefix handsontable --testPathPatternregex # 如果改动了 wrapper也要分别测试 npm run test --prefix wrappers/react-wrapper npm run test --prefix wrappers/vue3 npm run test --prefix wrappers/angular-wrapper--testPathPattern让你只跑受影响区域的测试避免全量回归的耗时而npm run build --prefix handsontable必须通过因为 React/Vue/Angular 三个 wrapper 的构建依赖 core 的产物。3. 目标分支所有 PR 都指向 develop仓库的合并基线是develop分支。对release/*或lts/*分支的 cherry-pick 由维护者单独处理贡献者无需自行操作。4. 填写 PR 模板逐段对齐机器可读仓库维护了一份官方 PR 模板 .github/PULL_REQUEST_TEMPLATE.md每个提交的 PR 描述都应镜像其全部###标题与 checklist 行。需要填写的部分Context—— 解释变更的原因而非仅仅列出改了什么关联 ClickUp 任务或 GitHub issue。How has this been tested?Test evidence—— 列出你新增或运行的测试单元、E2E、手工给出可复制重跑的测试命令。仓库强调能被机器重跑或评审人 diff 的才算证据。Commands run—— 粘贴实际执行过的测试命令及其最终输出行。Types of changes—— 勾选适用项bug fix、new feature、breaking change 或 translations。Related issue(s)—— 用#xxx关联 GitHub issue包含 ClickUp 任务 ID如DEV-627以触发自动链接。Affected project(s)—— 勾选变更涉及的所有包handsontable、handsontable/react-wrapper、handsontable/angular-wrapper、handsontable/vue3。Checklist—— 确认代码风格、CLA 签名以及是否需要更新文档。CLA 由必需的cla/signed状态检查自动校验一份签名同时覆盖 Handsontable 与 HyperFormula详见 CONTRIBUTING.md。模板一致性是被测试锁定的仓库中的 .github/scripts/tests/pr-template-skill-sync.test.mjs 会将 skill 内嵌的 body 模板与 .github/PULL_REQUEST_TEMPLATE.md 的标题、checklist 行逐条深比较——顺序、重复、缺失或措辞漂移都会导致测试失败且以模板为准。这意味着你在本地写 PR 描述时使用的模板结构与仓库 CI 期望的结构是强一致的。5. 先创建 PR再写 Changelog顺序是硬约束Handsontable 仓库的 changelog 文件以PR 编号命名因此必须先创建 PR、拿到编号再写 changelog 条目。顺序颠倒而猜测下一个 PR 号是不可靠的——在你检查与推送之间可能有其他 PR 被打开。标准流程在 feature 分支上提交代码变更。推送分支。运行gh pr create并捕获返回的 PR URL / 编号。用该编号创建 changelog 条目。始终以 Draft 形式创建 PR由作者在适当的时候标记 ready for reviewgh pr create --draft --base develop \ --title DEV-xxx: Short description \ --body-file /tmp/pr-body-DEV-xxx.md5.1 认证 fallback如果git push因会话中没有 SSH key 而报Permission denied (publickey)切换到 HTTPS 并让gh提供凭据git remote set-url origin https://github.com/handsontable/handsontable.git gh auth setup-git git push -u origin branch-name5.2 PR body 必须写入临时文件禁止 shell 命令替换禁止--body $(cat EOF...EOF)heredoc 经 shell 命令替换传入时反引号会被存储为字面 字符GitHub 上 PR 描述中所有内联代码格式都会被破坏。正确做法是先用 Write 工具将 body 写入临时文件再用--body-file传入用 Write 工具写/tmp/pr-body-task-id.md例如/tmp/pr-body-DEV-1860.md无需 shell 转义。通过--body-file /tmp/pr-body-task-id.md传给gh pr create。临时文件名必须按任务唯一不要用固定的/tmp/pr-body.mdWrite 工具拒绝覆盖本会话未读过的文件上一会话残留的/tmp/pr-body.md会导致写入报 Error writing file.。按分支的任务/issue ID 命名/tmp/pr-body-DEV-1860.md、/tmp/pr-body-issue-11832.md若路径已存在追加短唯一后缀如/tmp/pr-body-DEV-1860-2.md。5.3 每次都以 live 模板为准每次创建 PR 都要先cat .github/PULL_REQUEST_TEMPLATE.md逐一镜像其中的###标题与 checklist 行——包括保持未勾选状态的MANUAL QA NEEDED行。该行会被 Checks scope router.github/workflows/checks.yml机器读取措辞必须原样保留缺失该行意味着该 PR 永远无法在不动描述的情况下武装人工验收门禁。可用的 body 文件模板用 Write 工具写入反引号与 checklist 原样保留无需转义### Context The PR fixes/adds/changes what. Why the change is needed; link the task and explain the problem. ### Test evidence (required for source changes) - Unit tests added/modified (*.unit.js): paths, or none — covered by path - E2E tests added/modified (Playwright tests/e2e/*.spec.ts): paths - Type tests (*.types.ts) updated if public API changed: paths, or none - For a bug fix — the spec that fails without this fix: name - Demo page / recorded trace (for UI changes): link, or none ### Commands run bash the test commands you ran, one per block their final output lines ### Types of changes - [x] Bug fix (non-breaking change which fixes an issue) - [ ] New feature or improvement (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) - [ ] Additional language file or change to the existing one (translations) ### Related issue(s): 1. DEV-xxx ### Affected project(s): - [x] handsontable - [ ] handsontable/angular-wrapper - [ ] handsontable/react-wrapper - [ ] handsontable/vue3 ### Checklist: - [x] I have reviewed the guidelines about Contributing to Handsontable and I confirm that my code follows the code style of this project. - [x] I have signed the Contributor License Agreement — one signature covers both Handsontable and HyperFormula; the cla/signed check on this PR confirms it. - [ ] My change requires a change to the documentation. - [ ] MANUAL QA NEEDED — !-- one line: WHAT to check and why automation cant judge it. Also add the red Requires Manual QA label (that exact name — it already exists; QA needed and Verified by QA are different labels). Ticking holds the Tests run for a manual-qa environment approval by a designated reviewer (never whoever triggered the run). The box is read once per run, so if you change it after the pipeline ran, press Re-run all jobs. This line is machine-read — keep its wording. -- ClickUp task: task-url/DEV-xxx其他填写要点Commit message描述性最长 80 字符包含任务 ID如DEV-627: Fix filter column index。适用时在PR title中附带 ClickUp 任务 ID。Context段落以 The PR fixes/adds/changes/... 开头直入主题不加铺垫。若引入 breaking change必须加Breaking change标签并在描述中提供含 before/after 示例的迁移章节同时更新 docs/content/guides/upgrade-and-migration/ 下的迁移指南。5.4 MANUAL QA 机制机器读取的勾选框 人工审批门禁勾选 checklist 中的MANUAL QA NEEDED行后还必须手动添加红色Requires Manual QA标签仓库中已存在不要新建gh pr edit number --add-label Requires Manual QA注意gh label list --search Manual QA还会返回QA needed和Verified by QA——它们是语义不同的标签必须精确匹配Requires Manual QA而非近似命中。创建近似名如Manual QA required会静默产生第二个没人筛选的红色标签。该标签只是标记。真正的门禁是勾选框本身其底层实现可以从源码中完整验证路由.github/workflows/checks.yml 的manual-qastep 使用正则/^\s*-\s*\[[xX]\]\sMANUAL QA NEEDED/m对livePR body 做匹配而非冻结的 event payload输出requested供后续 workflow 使用。门禁.github/workflows/manual-qa.yml 的sign-offjob 引用manual-qa环境GitHub 会挂起该 job直到指定评审人在 Review pending deployments 中批准运行sign-offstep 再通过 approvals API 断言本 run 确实记录了一次针对manual-qa环境的 approval——fail closed即环境缺失或未配置 required reviewers 时直接失败而不是静默放行。该机制刻意按 run 生效勾选框在 pipeline 启动时被读取一次。pipeline 已全绿之后再勾选并不会武装任何东西必须点击Re-run all jobs取消勾选亦然。批准也是按 run 的每次新 push 都会重新请求一次评审。5a. 更新已有 PR 的 Body需要更新/修复/重填 PR 描述时使用同样的临时文件方案用 Write 工具把 body 写到/tmp/pr-body-task-id.md再执行gh pr edit number --body-file /tmp/pr-body-task-id.md固定的/tmp/pr-body.md会在存在上一会话残留副本时失败Write 工具不覆盖本会话未读过的文件。务必保留完整模板结构不要用更短的摘要替代同样禁止--body $(cat EOF...EOF)形式因为 Write 工具输出中的反引号不会做 shell 转义会在 GitHub 上存成字面 。6. Changelog Entry在 PR 创建之后所有改动源码的 PR 都必须在 .changelogs/ 下添加条目。bin/changelog以条目的issueOrPR字段命名文件private条目默认文件名就是PR 编号这正是不必也不能在开 PR 前写 changelog 的根本原因public条目则以 GitHub issue 编号命名因为该编号在 PR 存在前已知可以与代码一起提交无需上述往返。issuesOrigin的选择由 .changelogs/README.md 决定写条目之前务必先读它。6.1 非交互会话必须显式传参bin/changelog entry只在 stdin 是 TTY 时交互式提示Agent 的 shell 不是 TTY因此每个字段都必须以 flag 传入——而且有两个关键字段不在--help里--issuesOrigin完全未声明声明的--issue是死参数builder 实际读取issueOrPR传--issue会被静默丢弃并在assertChangelogEntryFormat处以堆栈崩溃。可用的调用方式bin/changelog entry Fixed …, ending with a period. \ --type fixed --issuesOrigin private --issueOrPR PR-number \ --breaking false --framework none命令会打印目标路径和编译后的 markdown 行据此确认条目落到了预期位置。6.2 两条阻塞性检查文件名必须为issueOrPR.json纯数字、无后缀且必须与条目内issueOrPR字段一致——bin/changelog的consume/sync及 pre-push hook 都会校验changelogjob 与本地推送均会因此失败。一个 PR 最多两个条目文件第二个仅用于该 PR 顺带关闭的独立 GitHub issue维护型 PR 为其他 PR 补填条目时需在描述中写[multiple changelogs]来解除上限。用npm run changelog entry生成条目天然满足文件名规则手工写 JSON 恰恰是破坏它的方式。6.3[skip changelog]与[multiple changelogs]仅测试、仅文档或 CI/工具链变更可在 PR body 中写[skip changelog]必须位于 HTML 注释之外模板注释内的提示是故意惰性的此时不需要PR-first 往返直接开 PR 即可。[multiple changelogs]与[skip changelog]是独立的标记后者回答这个变更是否需要条目从不解除条目数量上限。由于 changelog 检查在运行时读取 PR body编辑描述本身不会重新触发检查需要重新运行失败的 Changelog 检查或推送任意新提交git commit --allow-empty有效。6.4 private 条目的收尾写完文件后在同一分支提交DEV-xxx: Add changelog entry for PR #number。推送让 PR 拾取新提交。7. PR 创建之后更新 ClickUp 任务状态从 ClickUp 任务出发工作时使用 ClickUp MCP 工具把任务状态更新为code review。8. 合并策略Squash and merge所有 PR 都以Squash and merge方式合入。squash 后的提交信息将成为永久历史所以 PR 标题必须清晰、描述准确。9. 规则速查环节规则依据分支名feature/、docs/、release/前缀 人类可读任务 IDSKILL 分支命名章节预检eslint / stylelint / build / unit / e2e / wrapper 测试全绿SKILL 预检命令目标分支一律developSKILL 第 4 节PR 模板镜像 .github/PULL_REQUEST_TEMPLATE.md 全部标题与 checklistpr-template-skill-sync.test.mjs 测试锁定创建顺序先gh pr createdraft拿编号再写 changelog文件名依赖 PR 编号Body 传递Write 工具写/tmp/pr-body-task-id.md--body-file反引号转义问题MANUAL QA勾选框 Requires Manual QA标签 Re-run all jobschecks.yml 正则路由、manual-qa.yml 环境门禁Changelogbin/changelog entry--issuesOrigin private --issueOrPR PR号.changelogs/README.md、bin/changelog合并Squash and merge标题即永久历史SKILL 第 8 节这套流程的价值在于把开一个合规 PR从人工记忆变成了机器可校验的工程契约——分支名决定任务关联预检命令决定 CI 起点模板与勾选框决定路由与门禁changelog 命名决定发布历史。遵循它你的每个 PR 都能在最少往返的情况下通过所有自动化关卡。【免费下载链接】handsontableJavaScript Data Grid / Data Table with a Spreadsheet Look Feel. Works with React, Angular, and Vue. Supported by the Handsontable team ⚡项目地址: https://gitcode.com/gh_mirrors/ha/handsontable创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考