mcpField
G
gh-fix

gh-fix

github.com/lsegal开发571 次安装1 周前更新
代码仓库

关于 gh-fix

gh-fix 是用于自主处理 GitHub Issue 的 Agent 技能,涵盖验证、实现、拉取请求、CI 和合并。它在独立克隆中工作,可恢复现有拉取请求,并在缺少合并授权时暂缓合并。

主要功能

  1. 01验证并解读 GitHub Issue
  2. 02恢复符合条件的未关闭拉取请求
  3. 03将多项任务拆分为子 Issue
  4. 04在独立克隆中实现修复
  5. 05跟进 CI 并合并或暂缓拉取请求

适用场景

  1. 01自动完成获准合并的 Issue 修复
  2. 02在中断后继续处理已有工作
  3. 03将可独立完成的任务拆成子 Issue

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/lsegal/glorp --skill gh-fix

安装后在 Claude Code 中输入/gh-fix确认已加载。

附带文件agents/openai.yaml

详细介绍

通过合并修复 GitHub 问题

将 /gh-fix OWNER/REPO#ISSUENUMBER 视为授权你实现、发布、持续修复并合并该问题的修复方案。调用时可以附加 identity:/glorp:<ID>,以标识派发该任务的 Glorp 实例。自主工作,直至 PR 合并、问题不再授权合并,或出现需要用户介入的真正外部阻碍。绝不要更改用户现有的检出;所有更改都必须在单独的克隆中进行。

验证请求

  1. 必须提供且仅提供一个正整数 GitHub issue 编号;可选地在前面加上 #。此工作流在任何提及该 issue 的地方(分支、提交、PR 正文、评论和后续跟进)都必须使用 GitHub 风格的 #NNN 引用。绝不能用环境中其他跟踪系统的标识符(例如 ABCD-123)代替 issue 编号,即使该标识符出现在 issue、提交或其他上下文中也不行。还可选地接受一个末尾参数 identity:/glorp:<ID>,并在处理评论时保留该身份。如果存在身份参数,还可在其后接受可选的末尾指示 and do not merge,将其作为本次运行的禁止合并指示。如果存在身份参数以及禁止合并指示,还可在它们之后接受进一步的可选末尾指示 and no changelog,将其作为本次运行的不添加变更日志指示:跳过“修复实现”中的第 4 步,且不添加变更日志条目,无论 issue 或仓库规范原本有何要求。
  2. 确定 GitHub 仓库。优先使用命令本身直接给出的 OWNER/REPO(/gh-fix OWNER/REPO#N,glorp 始终会以此形式分派)——这是权威形式,无需进一步检测。如果命令是以裸形式 /gh-fix N 调用,则查找调用中的其他位置是否有 Repository: OWNER/REPO 行,或用户是否以其他方式明确说明了 OWNER/REPO,并使用该信息。只要以上任一形式提供了仓库,就绝不能运行 git remote -v、gh repo view 或任何其他仓库检测命令。仅当调用中的任何位置都未提供仓库时,才回退到当前检出分支的 GitHub 远程仓库以推断 OWNER/REPO;只有这样仍无法确定仓库时,才询问用户。
  3. 必须具备 git、gh,且 gh 会话已通过身份验证并拥有仓库和工作流访问权限。如果 issue 存在,但无法满足此项或任何其他环境要求,则停止,不得创建拉取请求或以其他方式修改仓库——但必须按照下方规则在该 issue 上发布一条评论,说明未实现修复的原因。
  4. 阅读 issue 标题、正文、标签、评论、状态和关联上下文。提供了身份时,还要按时间顺序以线程对话的形式阅读所有 issue 评论和关联的拉取请求对话:issue 正文构成初始请求,之后的评论可以修改、澄清或覆盖该上下文。包含对所提供身份的精确提及 @/glorp:<ID> 的评论是直接发给本 Agent 的指示,不得忽略;提及其他身份的内容不是本次运行的指示。如果 issue 不存在,则停止;无需发布评论。如果 issue 不可执行,或已关闭,则停止,不得创建拉取请求或以其他方式修改仓库——但必须按照下方规则在该 issue 上发布一条评论,说明未实现修复的原因。
  5. 在编写任何代码之前,确定该 issue 是否不予合并授权,并记录此决定。以下任一情况均视为禁止合并指示:标签表明暂缓合并(donotmerge、do-not-merge、do not merge、no-merge、hold、needs-review),匹配时不区分大小写,并忽略空格、连字符和下划线;或 issue 正文或评论中的任何措辞——包括发给本次运行的 @/glorp:<ID> 指示——要求不要合并该修复、保持开启状态,或在合并前停止。按时间顺序阅读对话:较新的评论可以提出或解除暂缓指示,因此以最近的表述为准。存在该指示时,记录其确切标签,或引用其来源措辞,并在整个运行过程中遵循:直至将拉取请求标记为就绪(含该步骤在内)的所有操作仍须照常进行,并以“禁止合并时暂缓拉取请求”代替合并。
  6. 阅读仓库说明,包括适用的 AGENTS.md、贡献指南、分支和 PR 规则、CI 配置以及变更日志规范。 放弃前务必评论并跟踪后续工作。 无论何种原因,只要此技能在为该 issue 创建 pull request 之前停止运行——例如 issue 无效或无法执行、缺少环境要求、存在无法消除的歧义、工具反复失败,或在此工作流的任何更早阶段遇到其他阻碍——结束运行前都必须在该 issue 上发布且仅发布一条评论,说明尝试过什么以及为何未实施修复,除非用户明确要求改为执行后续工作。在“将多部分 issue 拆分为子 issue”下创建的跟踪 issue 不属于阻碍,且不受此规则约束:首次拆分时评论一次;之后每次运行若没有新的内容可说,则不再评论。即使从未创建草稿 pull request,也必须遵守此规则。pull request 创建后,之后遇到的阻碍应根据“推动 CI 完成”在 pull request 上报告,而不是在 issue 上发表新评论。在上述任一情况下停止前,都要创建或关联所有可执行的后续 issue,并按“创建后续 issue”中的要求分派。这能让原因和下一步具体工作都显示在 GitHub 上,而不只是写在发给调用者的最终报告中。

恢复现有工作(可重入模式)

在遭到中断(Ctrl+C、会话崩溃、之后启动新会话)或由调用者从先前运行中移交后,/gh-fix N 必须能够安全地再次运行。创建任何新内容前:

  1. 确定 N 指向的是 issue 还是已打开的 pull request。如果 N 是 pull request,则从其正文中的 Closes #<ISSUENUMBER> 行找到它关闭的 issue,将其视为源 issue,并推动该 PR 本身直至完成,而不是另开一个。
  2. 如果 N 是 issue,则查找关闭该 issue 的 pull request,并将分支命名约定 fix/issue-N-* 和 PR 正文中的 Closes #N 作为匹配信号。绝不要复用 CLOSED pull request,无论它是否已合并——只有 OPEN pull request 才可以恢复,且不论匹配的是哪个信号。如果存在匹配的 open pull request,则恢复该 PR 和分支,而不是创建新草稿;否则,就按未找到处理,即使有已关闭的 PR 匹配也一样。
  3. issue 或 PR 的归属(判断是否可以安全接手,还是仍由其他 Agent 认领)由调用者在此技能启动前确定,而非由此技能确定。不要阅读或发布 PR 或 issue 评论来协商归属。
  4. 恢复工作时,克隆现有分支(而非默认分支),以保留其提交历史、检查点和任何未完成的实现。阅读 PR 正文,以了解已完成和已测试的内容,以及剩余工作。
  5. 克隆后,像从新建分支开始一样,继续执行此工作流的其余部分:持续创建检查点,直到确实准备就绪前都保持 PR 为草稿,并推动 CI 直至完成。如果先前的工作仍然有效,不要从头重新开始实现。

将包含多个部分的问题拆分为子问题

如果一个问题明确描述了多个可分离的工作内容,它就是一个跟踪问题,而不是一个工作单元。请在克隆任何内容之前做出一次判断,并且绝不要重复拆分同一个问题。

  1. 先阅读问题已有的子问题。 如果问题已经有一个或多个子问题,就说明它已被拆分。绝不要为它创建更多子问题,也绝不要为它创建拉取请求:对于此类问题,/gh-fix 唯一要做的事就是判断它是否可以关闭。阅读每个子问题的状态。如果所有子问题都已关闭,且父问题自身正文中没有尚未实现的内容,就通过评论列出已完成的子问题,然后关闭父问题。如果仍有任何子问题处于打开状态,则在结束运行时报告哪些子问题仍未关闭,且不要发布评论——如果运行没有新内容可说,就应保持问题不变,以免重复调度时累积相同的评论。无论哪种情况,都应在此处结束运行,不要克隆、创建分支或拉取请求。
  2. 绝不要拆分已有进行中工作的 问题。 如果“恢复现有工作”匹配到该问题的一个打开的拉取请求,就恢复该拉取请求,并完全跳过本节。
  3. 只有当问题本身明确说明了多个不同且可分离的任务时,才拆分。 务必非常谨慎。一个问题中的任务通常在开始时无法确定是否可分离,而错误拆分的代价高于不拆分。只有当每个部分都说明了自己的交付成果,并且无需其他部分就可以独立实现、测试和合并时,才进行拆分:“实现修复并更新文档网站”是两个任务。以下情况不要拆分:多个部分只是用不同说法描述同一项更改;某个部分无法在没有另一部分的情况下验证甚至实现;或者拆分依据是你自己的推断,而非问题本身的措辞:“实现此功能并修复相关的查找错误”通常是一个任务,因为只有实现该功能后才会触及此错误。如有疑问,就不要拆分——将该问题作为一项修复来实现,并按原样继续此工作流的其余部分。按照“创建后续问题”中的定义,仅需手动处理的部分永远不算可分离任务:绝不要为其创建子问题,也不要将它计入拆分。
  4. 如果确实需要拆分,请在同一仓库中为每个部分分别创建一个问题,并使用 GitHub 的子问题 API,通过父问题和新问题的 GitHub 问题 ID 将其关联到原始问题。不要只创建 Markdown 清单或简单提及。为每个子问题设置明确聚焦的标题,并提供足够的背景和验收标准,使其无需重新阅读父问题也能执行。混合手动检查与自动化工作的部分,应仅针对其中的自动化工作创建子问题。
  5. 按照“创建后续问题”的规则为每个新子问题准确分配:根据子问题本身选择标签,只保留仍然适用的标签,继承父问题的里程碑和受指派人,复制父问题的项目归属并将状态设为 Todo,其他方面则遵循 .glorp.json 中的分配规则。这样下一个 Agent 时段就能接手该子问题。创建、关联或分配子问题失败时,应将其视为需要采取行动的错误并重试。
  6. 创建子问题后,父问题就是一个跟踪或元问题。关闭它不需要拉取请求、代码或变更日志条目,并且不得占用 Agent 时段。只发布一条评论,列出已创建的子问题,并说明待所有子问题完成后将关闭父问题;对于仅需手动处理的部分,也要在同一条评论中列入 Manual verification 清单,然后结束运行,不要克隆、创建分支或打开拉取请求,以便下一个 Agent 时段可以接手某个子问题。

处理开放的阻塞问题

如果仓库支持 GitHub 堆叠拉取请求(gh-stack),被另一个未关闭议题阻塞的议题无需等待该议题。请在验证期间、克隆之前确定这一点,并记录下来,供本次运行后续步骤使用。恢复未关闭的拉取请求时,请跳过本节;其基础分支已记录该请求是否为堆叠式。

  1. 收集此 issue 的未解决阻塞项:gh api repos/<OWNER>/<REPO>/issues/<ISSUENUMBER>/dependencies/blocked_by 中的每个未解决 issue,以及 issue 正文中 Depends on #<N> 行所提及的每个未解决 issue。
  2. 使用 gh api repos/<OWNER>/<REPO>/stacks?per_page=1 检测仓库是否启用了堆叠式拉取请求。请求成功表示已启用;404 Not Found 表示未启用。
  3. 仅当已启用堆叠式拉取请求、恰好有一个未解决阻塞项,且该阻塞项有一个会关闭它的未解决拉取请求时,才进行堆叠。记录该阻塞项拉取请求的编号和 head 分支,作为堆叠基准。其他情况下都不要堆叠:按照本工作流其余部分的说明,从默认分支构建。
  4. 如果扩展尚未安装,则使用 gh extension install github/gh-stack 安装。如果无法安装,仍按下文说明堆叠分支和拉取请求,但跳过 gh stack 命令,并在拉取请求正文中说明无法关联堆叠。
  5. 从阻塞项的 head 分支创建新分支,而不是从默认分支创建;并将草稿拉取请求的目标分支设为该分支,而不是默认分支。草稿拉取请求的其他设置保持不变。
  6. 使用 gh stack link 在 GitHub 上将拉取请求关联为堆叠。如果阻塞项的拉取请求已属于某个堆叠(gh api repos/<OWNER>/<REPO>/stacks?pull_request=<BLOCKERPR>),则按从底到顶的顺序传入该堆叠中的拉取请求,后接此拉取请求;否则传入 <BLOCKERPR> <PRNUMBER>。在拉取请求正文中提及阻塞项的拉取请求。
  7. 阻塞项的分支属于另一次运行。绝不要提交到该分支、对其进行变基、推送或合并,也绝不要使用 gh stack merge 合并整个堆叠。同样也不能使用 gh stack sync 和 gh stack push,因为它们会推送堆叠中的每个分支。
  8. 每次推送前以及等待 CI 期间,都要检查上游是否有变更:获取并比较阻塞项的 head 分支与此分支的基准。如果阻塞项已有更新或已合并,则从此分支运行 gh stack rebase --upstack 更新此分支(阻塞项已合并时,它会自动切换为 --onto);解决任何冲突,重新运行受影响的检查,并仅推送此分支:git push --force-with-lease=<BRANCH>:<PREVIOUSREMOTESHA> origin <BRANCH>。在 gh stack 变基后,通过租约保护推送此运行自己的分支,是唯一允许强制推送的例外。没有扩展时,则将阻塞项的分支合并到此分支,并正常推送。
  9. 阻塞项的拉取请求合并后,确认此拉取请求的目标分支现已是默认分支;如果 GitHub 没有自动调整,则使用 gh pr edit <PRNUMBER> --base <DEFAULTBRANCH> 修改目标分支,然后照常在新 head 上运行 CI。如果阻塞项的拉取请求在未合并的情况下关闭,则使用 gh stack unstack 取消堆叠,按相同方式将此分支变基到默认分支,修改拉取请求的目标分支,并在拉取请求中报告已关闭的阻塞项。
  10. 如果堆叠式拉取请求的目标分支不是默认分支,绝不要合并它。一旦拉取请求已标记为就绪且 CI 通过,而阻塞项的拉取请求仍处于打开状态,就结束本次运行,不要等待阻塞项合并:在拉取请求上发布一条评论,说明它已就绪并暂时停放在阻塞项的拉取请求上;将停放的拉取请求作为结果报告,而不是报告为失败或阻塞项。不要创建后续 issue,也不要关闭此 issue。glorp 派发运行时,glorp 会将其停放、释放其 Agent 槽位,并在阻塞项不再处于打开状态时再次派发该 issue。后续运行会继续处理此拉取请求,遵循第 9 步,运行 CI,并继续执行“合并并验证”。如果 CI 通过时阻塞项已经合并,则在本次运行中遵循第 9 步,而不是结束运行。

创建隔离克隆和分支

  1. 确定规范的 OWNER/REPO、克隆 URL 和默认分支。
  2. 在切换目录之前,记录调用目录中是否包含 .glorp.json。保留此信息,以便后续路由使用,因为状态文件通常会被忽略,不会出现在隔离克隆中。
  3. 在当前检出目录之外创建一个名称唯一的同级目录或临时目录,例如 <repo>-gh-fix-<N>。绝不要重复使用或修改用户当前的工作树,也不要用 worktree 代替独立克隆。
  4. 正常克隆仓库。如果按上述章节恢复工作,则克隆并检出已有分支,并验证其 HEAD 与远程一致;否则,验证克隆的默认分支 HEAD 与远程一致。
  5. 验证克隆后立即输出 GLORP_CHECKOUT_DIRECTORY=<absolute clone path>,作为一行原样的纯文本进度信息,不添加 Markdown 格式。这使调用方能够显示并保存实际的隔离检出路径。如果恢复工作时重新生成了缺失的检出目录,则再次输出此行。
  6. 如果不是从已有分支恢复工作,则从当前远程默认分支创建新分支;如果“基于未解决的阻塞问题堆叠”决定进行堆叠,则从阻塞项的头分支创建新分支。优先使用 fix/issue-<N>-<short-slug>,除非仓库说明要求采用其他命名方案。
  7. 创建本工作流使用的每个克隆目录后,立即注册清理操作。退出前删除这些目录,包括正常完成、发生错误或出现 panic 时。不要删除用户已有的检出目录或无关目录。

清理必须无条件执行:每创建一个克隆目录,就立即使用延迟执行/finally 风格的清理保护机制;清理出错时,应明确显示错误,同时保留原始失败信息(如有)。

打开草稿拉取请求

创建分支后立即推送并打开草稿拉取请求,以便在整个开发过程中展示进度。如果按上述“恢复已有工作”章节恢复已有草稿 PR,则完全跳过本节——该 PR 已经打开。

  1. 创建一个空的初始提交,例如 Start work on issue #<ISSUENUMBER> [skip ci],然后推送新分支并设置上游跟踪。[skip ci] 标记可避免 CI 在与默认分支内容相同的树上运行;只有此提交和“实现修复”中描述的检查点提交可以带有此标记。绝不要强制推送。
  2. 针对当前默认分支,或在堆叠时针对阻塞项的头分支,打开一个简洁标题描述预期修复内容的草稿 PR。
  3. 编写真实的 Markdown 正文,总结问题和计划开展的工作。将完整的多行 Markdown 写入文件或通过标准输入传递,并使用 gh pr create --body-file(或等效的 gh pr edit --body-file)提交;绝不要在 --body 参数中使用字面量 \n 转义序列表示段落换行。单独占一行写入 Closes #<ISSUENUMBER>,以便草稿 PR 关联原始问题,并在合并时将其关闭;然后读回已创建的 PR 正文,确认其中包含实际换行,而不是字面量 \n 文本。
  4. 正文末尾添加 **Agents:** 页脚行,注明当前负责处理该问题的 Agent CLI 和模型(例如 **Agents:** claude-code (claude-sonnet-5)),并根据自身运行时上下文确定。这是下文所述的贡献 Agent 页脚。
  5. 记录 PR 编号和 URL,然后确认头分支和基础分支正确。
维护贡献 Agent 页脚

每次编写或替换 PR 正文(创建草稿、更新检查点以及标记为可审查)时,都要保留 **Agents:** 页脚,而不是覆盖它:

  1. 先读取当前 PR 正文,并找到其中的 **Agents:** 行(如果有)。
  2. 根据运行时上下文确定你当前使用的 Agent CLI 和模型。
  3. 如果缺少页脚,只添加你自己的条目。如果页脚已列出一个或多个 Agent/模型条目,则保留所有不重复的现有条目,并且仅在尚未包含你自己的条目时追加该条目;条目以逗号分隔,并按出现顺序排列(例如 **Agents:** codex (gpt-5), claude-code (claude-sonnet-5))。
  4. 这样,页脚就会累积所有处理过该问题的 Agent 和模型;当其他 Agent 或模型中途接手草稿时,这一点很重要。

实现修复

  1. 在可行的情况下,复现或以其他方式验证所报告的行为。
  2. 检查相关代码和历史记录,然后根据仓库惯例实现最小且完整的修复。
  3. 如果仓库有适用的测试框架,添加或更新有针对性的测试,确保没有此修复时测试会失败。
  4. 不区分大小写地查找现有变更日志,包括项目特定的路径和名称。在当前未发布部分下添加简洁、面向用户的说明,并遵循其格式。如果项目没有变更日志,不要新建;完全跳过此步骤,并在 PR 正文中说明项目没有变更日志,因此未添加条目。仅为用户可见的变更添加变更日志条目;不要添加仅涉及内部变更的说明。若修复的是另一条尚未发布的变更日志条目,不要添加条目。如果生效了禁止添加变更日志的指令,则完全跳过此步骤,不添加任何变更日志条目:此类指令包括验证给出的 and no changelog 分派建议,或问题正文及其评论中的任何措辞(包括发给本次运行的 @/glorp:<ID> 指令),只要要求此次修复跳过、不修改或忽略变更日志。请在 PR 正文中说明有意跳过变更日志的原因。
  5. 开发期间,只要工作树有变更,每隔五分钟至少创建并推送一次检查点提交。提交说明可使用 Checkpoint issue #<ISSUENUMBER> progress [skip ci] 这样的格式;保留 [skip ci] 标记,以免未完成的工作触发 CI 运行;不要等实现或测试完成后才向草稿 PR 发布下一个检查点。如果没有变更,则跳过空提交,并在下一个开发间隔后再次检查。绝不包含机密、生成的构建产物或无关变更。
  6. 先运行有针对性的测试,再运行仓库要求的更广泛检查。修复由此次变更导致的失败。不要将已知有问题的修复标记为可供审查。
  7. 检查状态和完整差异。只包含该问题、其测试和变更日志说明所需的文件。

捕获 UI 屏幕截图和屏幕录制

实现完成后,且仅在完成后,判断是否有任何更改的文件会影响用户界面。如果有:

  1. 捕获屏幕截图,展示具有代表性的最终状态中的已完成 UI 更改。如果更改涉及动画、交互或状态转换,则捕获屏幕录制来演示其行为,以替代或补充屏幕截图。对于动画,规划一系列操作,完整体验所有功能,包括错误处理等次要用例。
  2. 对于基于浏览器的界面,运行 UI 并使用可用的浏览器工具(例如 CDP 或浏览器自动化)捕获屏幕截图或屏幕录制。
  3. 对于基于终端的界面,如果没有视觉效果、动画或状态变化,则将输出复制为文本。
  4. 对于所有其他非浏览器界面,使用可用的本地应用或平台捕获工具。如果未安装合适的捕获工具,请安装 Loom 并用它创建屏幕录制。
  5. 捕获原生窗口时(任何浏览器之外的捕获,例如桌面应用或平台捕获工具),将屏幕截图或录制裁剪至相关窗口的边界。除非应用在捕获时确实处于全屏状态,否则绝不要保留全屏或全显示分辨率的捕获。
  6. 上传每张屏幕截图或每段屏幕录制,然后将返回的 URL 直接以 Markdown 格式嵌入拉取请求正文中(例如,![Dashboard after refresh](https://github.com/user-attachments/assets/...))。不要将 UI 屏幕截图或屏幕录制添加到仓库资源中,也不要将它们提交到分支。

GitHub 没有用于将文件附加到议题、拉取请求或评论的公开文档 API,但 Web UI 用于拖放的同一端点支持通过 bearer token 以非交互方式上传。直接使用该端点上传:

REPO_ID=$(gh api repos/<OWNER>/<REPO> --jq .id)
curl -sf -X POST "https://uploads.github.com/user-attachments/assets?name=<FILENAME>&content_type=<MIME_TYPE>&repository_id=$REPO_ID" \
  -H "Authorization: Bearer $(gh auth token)" \
  -H "Accept: application/json" \
  --data-binary @<LOCAL_FILE_PATH>

响应是包含 url 字段的 JSON(https://github.com/user-attachments/assets/<uuid>);将该 URL 嵌入拉取请求正文中。此端点未公开文档且非官方,因此如果出现失败或意外响应,请将其视为以下捕获错误之一,而不要无限重试。

只有在已完成的差异完全不影响任何 UI 代码时,才跳过本节。 如果尝试捕获或上传结果时遇到 2 个或更多错误,则跳过并在 PR 中说明。

提交并推送

本地检查通过后,创建最终实现提交,绝不要标记为 [skip ci],并使用简洁的祈使句作为主题行,将关闭关键词单独放在正文一行。如果最新检查点已包含所有最终更改,则创建一个空提交,以确保已检查的实现有明确的收尾提交:

Fix <concise issue summary>

Closes #<ISSUENUMBER>

例如,git commit -m "Fix parser handling of empty input" -m "Closes #123" 会在单独的正文行中创建所需内容。使用准确的目标议题编号,并按示例将 Closes 首字母大写。

如果提交消息的任何位置(包括主题行)包含跳过标记,GitHub 就会跳过该提交的 CI;而压缩合并会将 PR 标题和正文复制到默认分支上的提交中。绝不要在最终实现提交、CI 修复提交、PR 标题或 PR 正文中写入 GitHub 可识别的字面跳过标记([skip ci]、[ci skip]、[no ci]、[skip actions]、[actions skip] 或 skip-checks: true 尾注),即使更改与这些标记有关也不例外。请改用文字描述该标记,例如“跳过 CI 标记”。

最终推送前,确认分支包含预期代码、测试和变更日志说明;最终实现提交包含独立一行 Closes #<ISSUENUMBER>,且不含跳过标记;工作树干净;并且本地检查已通过。正常推送。绝不要强制推送。

将拉取请求标记为可审查

  1. 更新草稿 PR 的标题和正文,说明已完成的修复,包括根本原因、变更内容、对用户的影响、变更日志条目、测试,以及任何必需的 UI 截图或屏幕录制。将 Closes #<ISSUENUMBER> 保留在单独一行,并按照上述说明更新 **Agents:** 页脚,不要删除或覆盖它。标题和正文中不得包含「Commit and push」下列出的任何字面跳过标记。
  2. 确认头部分支、基准分支和变更文件范围正确。堆叠式拉取请求的变更文件只能包含此问题的变更,并且这些变更应基于阻塞问题的分支。
  3. 只有在实现、本地检查、最终推送以及任何必需的 UI 截图或屏幕录制均完成后,才将草稿 PR 标记为可供审查。

推进 CI 直至完成

继续操作,直到所有必需的检查都成功完成:

  1. 在判定成功前,确认预期的检查套件已为 PR 注册。创建 PR 后,检查列表暂时为空并不代表构建通过;请等待已配置或必需的检查出现,或者确认该代码库确实没有适用的 CI。
  2. 持续监控 PR 检查,不要只查看一次状态快照。优先使用 gh pr checks <PR> --watch --interval 10;使用产品提供的循环等待机制,让用户在耗时较长的构建期间定期收到进度更新。当以非交互方式运行(例如 glorp 分派此工作流时),请在前台阻塞等待监控完成,切勿在后台任务、监控器或计划唤醒仍在等待时结束本轮:本轮结束时进程会退出,从而中断等待。
  3. GitHub Actions 检查失败时,使用 gh pr checks、gh run view 和作业日志 API(如有必要)检查确切的运行记录和失败作业日志。在更改代码前,记录检查名称、运行 URL、失败的命令以及有用的错误上下文。
  4. 对于外部检查,请打开检查 URL,并使用服务提供方提供的日志或工具。如果无法访问日志,请报告访问受阻的情况,不要猜测。
  5. 对每项失败进行分类:
    • 如果失败由 PR 引起,请在实际可行时于本地复现,实施最小且正确的修复,运行相关本地检查,不使用「Commit and push」下列出的任何跳过标记提交修复,并正常推送。
    • 如果存在合并冲突,请从最新的默认分支更新分支,不要强制推送,解决冲突,重新运行受影响的检查,然后提交并推送。对于堆叠式拉取请求,请按照「Stack on an open blocking issue」中的说明从阻塞问题的分支更新。
    • 如果明显是临时基础设施故障或不稳定测试导致失败,请重跑失败的作业一次;若问题再次出现,则进行调查。
    • 如果明显是与 PR 无关且持续存在的失败,请收集诊断详情;只有在安全的情况下,才尝试修复范围内的问题。否则,请在确实受外部因素阻塞时停止。
  6. 每次推送或重跑后,都要监控新头部 SHA 的检查状态,直至检查完成。忽略早期 SHA 的过时结果。
  7. 对仍可处理的 CI 失败,重复诊断、修复、本地验证、提交、推送和监控步骤,直至全部解决。不要仅为获得通过结果而削弱断言、跳过测试、降低覆盖率或更改 CI。

合并被暂缓时保留拉取请求

当验证记录了禁止合并的指令时,本次运行会以一个已准备就绪但尚未合并的拉取请求结束。在此之前,一切照常进行:修复、测试、更新日志说明、最终推送、将拉取请求标记为可供审查,以及等待 CI 完成。只有合并和后续问题不会进行。

  1. 不要合并拉取请求,不要删除分支,也不要关闭发起的议题。绝不能因为 CI 结果为绿色或修复看起来已完成,就绕过暂缓指令进行合并。
  2. 在本次运行自身输出所示的位置记录该决定:注明暂缓合并的标签,或引用暂缓合并的原文,并说明拉取请求是有意保持开放、留待人工合并的。
  3. 在拉取请求上恰好发布一条评论,报告完成状态。说明工单状态为 Ready,概述修复、测试和 CI 结果,并说明合并已暂缓,同时注明相关标签或引用暂缓合并的指令。
  4. 对于暂缓合并的运行,不要创建、复用或转交任何后续问题——“创建后续问题”不适用,因为尚未合并的工作在审查过程中仍可能发生变化。相反,应在同一条拉取请求评论中以 Follow-ups (not filed) 为标题,列出所有原本会成为后续问题的事项;如果有等同的现有开放议题,应链接该议题,而不要新建任何内容,以便负责合并的人创建这些问题。按照“创建后续问题”中的说明对这些事项分类:纯人工处理的事项不要放入 Follow-ups (not filed),而应在同一条评论中用单独的 Manual verification 标题列出,并附上设置步骤和精确的检查内容。
  5. 发布该评论后结束本次运行,并将暂缓合并报告为最终结果,而不是失败或阻塞。

合并并验证

如果议题禁止合并授权,请完全跳过本节;改为遵循“合并被暂缓时保留拉取请求”。

  1. 合并前,获取最新的 PR 状态,并确认发起的议题和 PR 均仍处于开放状态。如果其中任何一个已关闭,则不要合并:议题已关闭意味着停止工作;未合并便关闭的 PR 表示本次尝试已被拒绝,不能重新打开或复用。然后确认其基准分支为默认分支(堆叠式拉取请求需等待阻塞它的 PR 先合并),至少有一次 CI 运行实际针对头部 SHA 注册,且该 SHA 上的每项必需检查均成功;确认 PR 可合并、没有必需审查或未解决的讨论阻碍合并、必需的 UI 截图或屏幕录制已提供,并且头部 SHA 就是通过 CI 的那个提交。如果头部 SHA 的检查列表始终为空,则不算通过:如果仓库配置了 CI,请检查头部提交消息以及 PR 标题和正文中是否有跳过标记,移除该标记并推送一个新提交,以便 CI 在合并前运行。
  2. 使用仓库要求或惯用的合并方式。当仓库允许多种方式时,优先级如下:压缩合并,然后合并提交,最后变基。在压缩合并时,使用 PR 的标题和正文作为压缩提交消息,不要覆盖它——正文已包含独立一行的 Closes #<ISSUENUMBER>。如果只允许合并提交或只允许变基,则改用该方式,并无论采用哪种方式都保留独立的关闭引用。
  3. 如果仓库政策允许,在成功合并后删除远程议题分支。
  4. 验证 PR 已合并、合并提交可从远程默认分支访问,并且 GitHub 已关闭议题 #<ISSUENUMBER>。允许 GitHub 有短暂的处理延迟,但未经检查不得声称议题已关闭。

创建后续问题

检查两个终止节点是否存在未解决的后续工作:在停止失败或停滞的运行前立即检查,无论是否已有拉取请求;以及拉取请求合并后检查。阅读源议题、任何拉取请求的正文和评论,以及当前对话,找出所有明确提及的阻塞项、待办事项或已知问题。运行即将停止时,不要等到合并后再检查。本节不适用于按“合并被阻止时保留拉取请求”结束的运行:保留的拉取请求不会创建任何后续议题,而是在其完成状态评论中报告相同事项。

创建议题前,先对每项进行分类。 如果某项只能由人工检查是否符合验收条件,则该项属于仅限人工处理:运行第三方 GUI 应用或主机、使用实体或外围硬件、使用真实设备或账户,或做出仓库无法测试的主观或视觉判断。绝不要将仅限人工处理的事项创建为议题:glorp 会将其分派给无法完成工作的 Agent 插槽,导致积压列表中充满没有 Agent 能够关闭的议题。

  • 将仅限人工处理的事项作为一条评论发布,并附上 Manual verification 检查清单。有拉取请求时,发布在拉取请求上;运行停止且没有拉取请求时,发布在源议题上;运行在拉取请求创建前就停止时,将检查清单并入该运行已发布的单条说明性评论中,不要另发第二条评论。逐项列出设置步骤和确切的检查内容,并说明 CI 无法覆盖这些检查。若先前的运行已发布相同且未更改的检查清单,则不要重复发布。
  • 如果某项同时包含人工检查和可自动化工作(例如脚本、测试框架、文档或打包),只将可自动化部分创建为后续议题,并将人工检查留在评论中。
  • 以下步骤仅适用于不属于仅限人工处理的事项,或此类事项中不属于仅限人工处理的部分。
  1. 将每个不同且可执行的事项分别在同一仓库中创建为一个 issue。不要为已完成的工作、模糊的观察或已有等效未关闭 issue 的事项创建 issue;应链接到现有 issue。
  2. 为每个新 issue 设置明确聚焦的标题,并提供足够的背景信息和验收标准,使其无需重新阅读拉取请求也能采取行动。
  3. 将每个新 issue 与其源 issue 关联;如果存在发现阻塞事项或剩余工作的拉取请求,也要与该拉取请求关联。支持时,优先使用仓库或项目关系元数据。否则,在 issue 正文中加入 Addresses #<ISSUENUMBER>;存在拉取请求时,再加上 and #<PRNUMBER>。
  4. 如果源 issue 存在尚未解决的 issue 依赖项,且后续 issue 要处理该依赖项,则将后续 issue 设为相关阻塞 issue 的子 issue。读取依赖关系和新 issue 的 GitHub issue ID,然后使用 GitHub 的子 issue API;不要只在 Markdown 中提及阻塞项。如果存在多个阻塞项,只将后续 issue 关联到它所处理的特定阻塞项;如果关系不明确,应请求指示,不要猜测。对复用的等效未关闭 issue 也应用相同的关系,除非它已经是该阻塞 issue 的子 issue。
  5. 每个新后续 issue 的标签都应根据后续 issue 本身确定,而不是照搬源 issue 的标签集合。先读取仓库可用的标签(gh label list),再为其添加与后续工作类型相对应的仓库标签:缺陷使用仓库中表示 bug 的标签(bug、bugreport、defect),新工作使用表示功能的标签(enhancement、feature、Feature)。标签名称必须与仓库实际定义的名称匹配,大小写不敏感,绝不可编造仓库未定义的标签;如果仓库没有对应标签,则不添加类型标签,也不要用近似标签替代。
  6. 只有源 issue 的标签对后续 issue 仍然准确时才予以继承。描述后续 issue 与源 issue 共有属性的标签——例如领域、组件、发布列车、优先级、milestone123 式分组——应予以继承。描述源 issue 本身、可能与后续 issue 矛盾的标签则不应继承:包括类型标签(例如,后续 issue 是功能请求时,源 issue 上的 bug 标签)以及分流或工作流状态标签(needs-triage、duplicate、wontfix、good first issue)。继承的标签绝不能覆盖上述为后续 issue 选择的类型标签;两者不一致时,应保留后续 issue 自身的类型标签,并舍弃源 issue 的类型标签。
  7. 将源 issue 的里程碑和指派人原样继承到每个新后续 issue。创建后续 issue 时,与上述决定的标签一并设置(gh issue create --label ... --milestone ... --assignee ...);或者创建后立即通过 gh issue edit 添加。仅跳过仓库无法接受的值——不存在的标签、已关闭或缺失的里程碑、无法指派的用户——并说明跳过了哪个值,不要因此省略整个步骤。不要编造源 issue 未指定的里程碑或指派人。
  8. 检查源 issue 的项目条目。如果它属于一个或多个 GitHub Projects,则将每个新后续 issue 加入相同的项目,并将每个新条目的 Status 设为该项目的 Todo 选项。匹配 Todo 时不区分大小写,但不得擅自选择其他状态。即使运行失败或停滞,也必须先完成此项目路由,再停止;合并后同样如此。
  9. 如果源 issue 不属于任何项目,且调用目录中存在 .glorp.json,则除了继承的指派人外,还应将每个新后续 issue 指派给已认证用户,以便 Glorp 能够调度它:使用 gh issue edit <NEWISSUENUMBER> --repo <OWNER/REPO> --add-assignee @me。使用克隆前记录的文件是否存在这一信息;不要假设被忽略的状态文件会存在于隔离检出目录中。不要将已认证用户添加到项目关联的后续 issue 中;这类 issue 仍应继承源 issue 的指派人。
  10. 对复用的等效未关闭 issue,也应应用相同的项目状态或指派人路由,除非它已经正确路由,或其当前项目状态表明工作已经开始或完成。只有在复用的 issue 在相应字段上没有任何自身值时,才添加上述决定的标签以及继承的里程碑和指派人,避免覆盖或移除其现有分流信息。
  11. 记录所有新建或复用的后续 issue 的 URL,以便在最终报告中提供。如果没有符合条件的事项,明确记录无需创建后续 issue。单独记录需要人工验证的事项,并提供列出这些事项的评论 URL。
  12. 创建 issue、建立源关联或必要的子 issue 关系、为后续 issue 添加标签或复制源 issue 的里程碑或指派人、指派所需用户、复制项目成员关系或设置 Todo 状态时若发生失败,应视为可执行错误并重试。不要在失败或停滞时结束运行;所需的后续 issue 工作尚未完成时,不得报告工作流已合并并完成。

报告结果

先说明合并结果。提供 issue 和 PR 的 URL、分支名称、最终提交或合并 SHA、克隆路径、变更日志文件、本地测试、已完成的 CI 检查、后续 issue 的 URL 或确认不需要后续 issue、手动验证项目及其评论 URL(与后续 issue 分开列出),或确认没有手动验证项目。提供 UI 截图或屏幕录制,或确认不适用。确认 PR 已合并且 issue 已关闭。如果确实受阻,请指出确切的失败步骤、相关 URL 或日志详情、剩余要求,以及为此创建或沿用的所有后续 issue;保留隔离的克隆和分支以便继续。如果运行因暂缓合并而以搁置 PR 结束,则不要先报告合并结果:先说明 PR 已就绪但尚未合并,指出相关标签或引用暂缓合并的原文措辞,提供完成状态评论的 URL,并将其中报告的后续事项列为未创建 issue,而不是 issue URL。如果运行因将堆叠 PR 暂停在尚未解决的阻塞项上而结束,则先说明这一点:报告 PR 已就绪但尚未合并,指出它在等待哪个阻塞 PR,并提供暂停评论的 URL。如果运行因该 issue 是跟踪 issue 而结束,请说明未创建 PR,列出已创建或已存在的子 issue 及其 URL 和状态,并说明父 issue 已关闭还是仍在等待未关闭的子 issue。如果工作流在验证期间停止且未创建 PR,请说明未创建 PR,引用停止原因,列出所有创建或沿用的后续 issue,并提供发布在该 issue 上的说明评论 URL(如果该 issue 不存在,则确认无需发布评论)。

清理克隆

删除隔离的克隆目录和任何临时文件。如果工作流受阻或失败,请保留克隆以供进一步调查,并向用户报告其位置。

评论

支持 Markdown