首页
/ Windows Terminal 的 Issue/PR 管理机器人:标签驱动的分诊体系与 GitOps 自动化实现

Windows Terminal 的 Issue/PR 管理机器人:标签驱动的分诊体系与 GitOps 自动化实现

2026-09-06 11:35:41作者:段琳惟

本篇围绕 doc/bot.md 中定义的 Windows Terminal 仓库 Issue/PR 管理机器人(Bot)机制展开:先完整还原其标签(Label)体系、分诊(Triage)流程与 Issue/PR 自动化规则的运作逻辑,再深入仓库中真正实现这些规则的 GitOps 策略文件,逐条印证文档描述背后的触发条件、执行动作与定时策略,帮助维护者和贡献者理解“一个 Issue 从创建到关闭”的完整生命周期由哪些自动化节点驱动。

设计目标:用标签把仓库“噪音”收敛为可执行的工作队列

doc/bot.md 开篇说明了这套机制的目标:自动化、管理并收敛这个大型仓库中真正需要关注的对象。核心手段是标签体系——借助标签来理解“什么需要处理、什么已经搁置变陈旧(stale)”。

对核心贡献者,文档给出了一份按优先级排序的快速指引:

  1. 优先查看 Needs-Attention,这是最高优先级;
  2. 在分诊会议(triage meeting)期间查看 Needs-Triage,掌握新动态并完成分类;
  3. 有空闲时间时处理 Needs-Tag-Fix,修复被错误标记的条目;
  4. 需要作者跟进时,手动添加 Needs-Author-Feedback——如果作者回来响应就优先与其互动,如果长期不活动则自动关闭。

这套标签体系在 资源管理策略 中有着完整落地:

  • Area- 前缀:标识问题所在的代码领域,策略文件中枚举了 32 个值,覆盖 Area-AccessibilityArea-AtlasEngineArea-RenderingArea-TerminalControlArea-SettingsUIArea-VT 等,与 src/ 下的模块划分(renderer、cascadia、terminal/adapter、types 等)基本对应;
  • Issue- 前缀:标识问题类别,共 7 个值:Issue-BugIssue-DocsIssue-FeatureIssue-QuestionIssue-SamplesIssue-TaskIssue-Scenario
  • Product- 前缀:标识所属产品,共 8 个值:Product-Cmd.exeProduct-ColortoolProduct-ConhostProduct-ConptyProduct-MetaProduct-PowershellProduct-TerminalProduct-WSL
  • Resolution- 前缀:标识关闭原因,包括 Resolution-AnsweredResolution-By-DesignResolution-DuplicateResolution-ExternalResolution-Fix-AvailableResolution-Fix-CommittedResolution-Won't-Fix

分诊的目标就是为每个条目打上符合 Product + Area + Issue 三类组合的标签;Needs-Triage 标签本身由核心贡献者团队在分诊会上手动移除(高负荷期间资深成员也可以离线完成)。

标签生命周期:从 Needs-Triage 到自动关闭的衰减链

doc/bot.md 定义了 Issue 与 PR 两条平行的标签流转链,其核心是一个“活跃度衰减”策略。

Issue 链路:

  1. 新 Issue 到达或标签缺失时,自动标记 Needs-Triage。这一点在 Issue 模板中已经前置完成:Bug 报告模板 声明了 labels: [Issue-Bug, Needs-Triage],即提交 Bug 时这两个标签直接随模板附上;功能请求模板 则附带 Issue-Feature 标签。策略文件中的 “Add Needs-Triage to new issues” 响应器 会兜底处理:对 Issues 事件中的 opened 动作,若条目没有 ⛺ Reserved 标签,就补加 Needs-Triage
  2. 核心贡献者需要向作者提问时,手动添加 Needs-Author-Feedback。作者一旦回到线程产生活动,该标签自动脱落,同时机器人补上 Needs-Attention 把条目重新推回核心团队视野——“如果作者愿意保持活跃,我们会优先与其互动”。
  3. 若作者长时间未回归,条目获得 No-Recent-Activity 标签;任何活动都会自动摘除该标签。
  4. No-Recent-Activity 持续存在,Issue 将被以 stale 关闭。

PR 链路采用类似但更宽松的衰减策略:评审者提出修改请求(changes requested)后 PR 自动获得 Needs-Author-Feedback;作者更新 PR、评论或响应评审都会摘除该标签;约 7 天无活动则打上 No-Recent-Activity,再持续 7 天后 PR 被 stale 关闭。

此外还有两条联动规则:

  • 手动标记为 Resolution-Duplicate 的 Issue,在活动停止后不久即被关闭;
  • AutoMerge 标签的 PR 在满足条件后由机器人完成合并与清理(见 AutoMerge 一节)。

这套链路的完整实现位于 resourceManagement.yml 的 scheduledSearches 部分,共 5 条每小时执行一次的定时搜索规则(详见下文)。

分诊快捷指令:/dup、/feedback 与 /?

doc/bot.md 定义了“Triage Shorthand”——供分诊团队加速完成分诊的快捷评论。使用前提:只有对仓库拥有 WriteAdmin 权限的人可以使用这些指令

/dup #:重复问题一键关闭

当线程中有人评论 /dup #<issue ID> 时,机器人执行四步:

  1. 回复评论,说明该 Issue 是重复项,建议发起者与关注者优先跟踪所列 ID 的 Issue;
  2. 关闭当前 Issue;
  3. 移除所有 Needs-* 标签;
  4. 添加 Resolution-Duplicate 标签。

策略文件中的实际实现比文档描述更精细:

  • 匹配正则为 \/dup(licate|e)?(\s+of)?\s+\#[\d]+,也就是说 /dup #123/dupe of #123/duplicate #123 都能触发;
  • 权限检查为 activitySenderHasPermission: Admin | Write,与文档一致;
  • 具体移除的标签枚举为 Needs-TriageNeeds-Tag-FixNeeds-AttentionNeeds-Author-FeedbackNeeds-ReproNeeds-Second,即把仓库实际在用的全部 Needs-* 标签逐一清除。

从实现看还有一条文档未提及的扩展规则:针对外部仓库的 /dup 变体——当评论形如 /dup https://...(指向其他仓库的 Issue Tracker)时,机器人同样关闭 Issue,但打的是 Resolution-External 标签,并提示订阅者关注外部线程,同时额外清理 Needs-Bisect 标签。

/feedback:引导使用 Feedback Hub 收集诊断数据

当线程中评论 /feedback 时:

  1. 机器人回复一段引导文案,请作者通过 Feedback Hub 提交数据并粘贴链接;
  2. 添加 Needs-Author-Feedback 标签。

对应实现 的回复文案还附带了操作细节:点击 “Start recording” 后再复现问题,并在提交后粘贴链接——这与 Bug 报告模板 中的提示(崩溃类问题请提供 Feedback Hub 提交链接,类别选 “Apps > Windows Terminal” 并 “Share My Feedback” 获取链接)形成呼应:模板负责事前提醒,/feedback 指令负责事中补救。

/?:把球踢回给作者

策略文件中还定义了 一条文档未单独列出的快捷指令:拥有 Write/Admin 权限的人评论 /? 时,机器人移除 Needs-Attention 并添加 Needs-Author-Feedback。可以推断,这条指令用于分诊时判断“还需要作者补充信息”的场景,是 /feedback 之外的轻量替代(不带 Feedback Hub 引导文案)。

Issue 管理自动化规则逐条解析

doc/bot.md 的 “Issue Management” 一节列出了 8 条规则。下面结合 resourceManagement.yml 的实现逐条说明其触发方式与参数。

1. 打 Needs-Triage:新 Issue 与标签不合规时

文档描述:Issue 不满足分诊标准时打上 Needs-Triage,“目前只在创建时触发”。

实现上由两个响应器协同:新 Issue 的 opened 事件触发补加 Needs-Triage;更复杂的是 “Enforce tag system” 规则——每当 Issue 被打开或标签发生任何变化,系统都会校验标签是否合规:所有打开的条目必须同时具备一个 Area-、一个 Issue-、一个 Product- 标签;已关闭的条目还必须有一个 Resolution- 标签。不合规且未打 Needs-Triage⛺ ReservedTracking-External 的条目会被加上 Needs-Tag-Fix。当三类标签补齐后,另一条响应器 会自动摘除 Needs-Tag-Fix。文档特别指出:Resolution-Duplicate 足以修复全部标签合规性(重复项无需 Area/Issue/Product 标签),实现中确实有专门的短路规则支持这一豁免。

2. 作者响应:Needs-Author-Feedback 换 Needs-Attention

当带 Needs-Author-Feedback 的 Issue 收到作者本人的评论时,响应器 检查 isActivitySender: issueAuthor: True,然后一次性完成“摘除 Needs-Author-Feedback + 添加 Needs-Attention”,把条目交还给核心团队。

3. 移除活动标签:任何活动摘除 No-Recent-Activity

文档说“带 No-Recent-Activity 的 Issue 一旦有活动就摘除该标签”。实现拆成两条响应器分别覆盖两类事件:Issue 被重新打开等非关闭动作有人评论

4. 关闭陈旧 Issue:3 天 stale 阈值

文档:每小时检查是否存在同时带 Needs-Author-FeedbackNo-Recent-Activity 且已 3 天无活动的 Issue,是则关闭为 stale。对应定时搜索 的过滤器链为 isIssue → isOpen → hasLabel(Needs-Author-Feedback) → hasLabel(No-Recent-Activity) → noActivitySince(3 days),动作为 closeIssue,执行频率为每小时整点(hour: 3)。

5. 标记无活动:4 天阈值 + 预告式提醒

文档:每小时检查带 Needs-Author-Feedback 的 Issue 是否已有 4 天无活动,是则补打 No-Recent-Activity实现 除了 addLabel 之外还有一条 addReply,发送固定的 stale 预告文案:“该 Issue 因标记为需要作者反馈且 4 天 无活动被自动标记为 stale,若此后 3 天 内仍无活动将被关闭。”——即提前告知作者两个关键时间点,让自动关闭可预期、可避免。

6. 关闭重复 Issue:1 天阈值

文档:手动标记 Resolution-Duplicate 的 Issue,若在最后一次活动 1 天后仍无动作即被关闭。实现 同样带预告回复:“该 Issue 已标记为重复且 1 天 无活动,将为保持整洁而关闭。”

7. 清理低质量 Issue:模板标题与空正文自动关闭

文档列出了三类低质量情形(标题不完整、正文为空、命中常见重复模式),说明机器人会自动关闭并提示作者修正后重新提交,且引用 “Bug/Feature templates” 作为典型情形。

模板标题规则的实现 非常具体:对 opened/reopened 事件,若标题正则匹配 Bug Report (IF I DO NOT CHANGE THIS THE ISSUE WILL BE AUTO-CLOSED)Bug Report(旧版模板的默认标题),且操作者没有 Write/Admin 权限(防止误伤内部操作),则关闭 Issue、添加 Needs-Author-Feedback,并回复:“很遗憾你的标题没有从模板中修改……请修正标题后重新提交。”

空正文规则 同理:正文正则 .+ 不匹配(即没有任何内容)就自动关闭并提示补全正文后重新提交。文档中提到的“命中常见重复模式”属于规划中的模式匹配,从当前策略文件看尚未见到对应的独立实现,可以推断这部分能力仍在演进中。

8. In-PR 联动:摘除 Help-Wanted

文档:当新 PR 创建导致 Issue 获得 In-PR 标签时,移除 Help-Wanted,避免有人重复投入已有修复提案的问题。实现 的触发条件是 Issues 事件中带 In-PRHelp Wanted 两个标签,动作是摘除 Help-Wanted

另外策略中还有一条 cleanEmailReply 规则:所有 Issue_Comment 事件都会触发邮箱回复格式清理——这是文档未提及但对邮件客户端用户很实用的细节:直接回复邮件产生的引用堆叠会被自动整理。

PR 自动化:从评审请求到 Squash 自动合并

doc/bot.md 的 “PR Management” 一节包含 8 条规则(含一条已禁用的 Codeflow Link)。逐条对应实现如下。

评审请求触发 Needs-Author-Feedback

响应器 监听 Pull_Request_Reviewsubmitted 动作,且 reviewState: Changes_requested 时添加 Needs-Author-Feedback。摘除该标签有两条路径:作者对 PR 的任何非关闭活动,以及 作者本人提交评审响应(文档只笼统写了“更新 PR、评论或响应评审”,实现按事件源拆得更细)。No-Recent-Activity 的摘除同样覆盖三类事件:PR 上的活动评论评审

Stale PR 的 7+7 天衰减

  • 7 天打 stale 标:带 Needs-Author-Feedback 且 7 天无活动的 PR 获得 No-Recent-Activity,并回复预告文案(“再 7 天 无活动将关闭”);
  • 再 7 天关闭:两个标签齐备且再 7 天无活动,执行 closeIssue

Issue 链路是 4 天 + 3 天,PR 链路放宽到 7 天 + 7 天——PR 往往涉及更长的开发迭代周期,从参数设计看是有意为之的差异。

AutoMerge:从评审请求到 Squash 自动合并

文档规定:当 PR 带 AutoMerge 标签时,若已等待至少 480 分钟且所有状态检查通过,机器人将其合并,且:

  • 使用 Squash merge 策略;
  • 合并后尽可能删除源分支;
  • 没有 Write 权限的人推送了新改动,自动移除 AutoMerge 标签。

实现 采用委托方式:带 AutoMerge 标签的 PR 上执行 enableAutoMergemergeMethod: Squash),标签被移除时执行 disableAutoMerge。从源码结构看,480 分钟等待、状态检查门禁、分支删除等行为实际由 GitHub 平台的原生 auto-merge 机制承载,GitOps 策略只负责“按标签开关”;文档末尾也注明,可通过评论控制的更细粒度 bot-logic 参考了微软另一个仓库的 Advanced auto-merge 方案。此外还有一个 labelSync 机制:任何 Pull_Request 事件都会同步 Issue-Area-Priority-Product-Severity-Impact- 六类前缀的标签,保证 PR 与其链接的 Issue 标签一致。

In-PR 标记、Resolution-Fix-Committed 与 Needs-Second

  • inPrLabel 响应器:任何 PR 事件都会给其引用的 Issue 打上 In-PR,对应文档中“为有活跃 PR 的 Issue 标记 In-PR”;
  • 文档要求 PR 完成后若关联 Issue 没有剩余工作,则补打 Resolution-Fix-Committed——该标签包含在 标签合规校验的 Resolution 集合 中,是关闭 Issue 的合法终态之一;
  • Needs-Second 机制:PR 被打上 Needs-Second 标签时,自动向仓库的五位核心维护者(zadjii-msft、PankajBhojwani、carlos-zamora、dhowett、lhecker)发起评审请求;PR 关闭时若仍带 Needs-Second,标签被自动移除。这条规则补充了文档“完成 PR 时移除 Needs-Second”的场景——它的实际用途是请求团队内部复审

实现载体:GitOps.PullRequestIssueManagement 原语

上述所有规则集中落在一个文件中:.github/policies/resourceManagement.yml,其 idGitOps.PullRequestIssueManagement,作用于 repository 级资源且 disabled: false。文件结构分两大块,理解它就能读懂整条规则链:

scheduledSearches(定时搜索)——5 条规则全部配置为每小时执行一次(hour: 3),各自持有独立的 filters 条件链(isIssue/isPullRequestisOpenhasLabelnoActivitySinceisNotLabeledWith)与 actionscloseIssueaddLabeladdReply)。这是“衰减与自动关闭”类规则的载体,特点是基于时间窗口的状态扫描

eventResponderTasks(事件响应器)——18 条规则,各自由 payloadTypeIssuesIssue_CommentPull_RequestPull_Request_Review)与条件(isActionisReviewStateisActivitySendercommentContains 正则、titleContainsbodyContains、权限检查)驱动,执行 addLabel/removeLabel/closeIssue/addReply/enableAutoMerge/inPrLabel/requestReview/cleanEmailReply/labelSync 等动作。这是“即时反应”类规则的载体,覆盖了上文所有分诊指令、标签交换与低质量清理。

举一个最小示例,新 Issue 自动打标的完整声明如下(摘自 resourceManagement.yml 第 93-105 行):

- description: Add "Needs-Triage" to new issues
  if:
  - payloadType: Issues
  - or:
    - and:
      - isAction:
          action: Opened
      - not:
          hasLabel:
            label:  Reserved
  then:
  - addLabel:
      label: Needs-Triage

可见规则表达是纯声明式的:if 链描述事件与谓词,then 链描述动作,无需编写任何代码。

配套的还有 addToProject.yml 工作流:监听 Issue 的 labeled/unabeled 事件,通过 actions/add-to-project 把条目同步到团队项目看板。值得注意的是其参数 label-operator: NOT 配合 labeled: Issue-Feature, Needs-Triage, Needs-Author-Feedback, Issue-Scenario——即排除带这些标签的条目。与 doc/bot.md 中“We're not focusing on Projects yet”的表述对照,可以推断项目看板只用于跟踪特定已分类条目,整体分诊流程仍以标签体系为唯一事实来源。

对贡献者的实用建议

  • 提 Issue 前config.yml 已禁用空白 Issue(blank_issues_enabled: false),安全漏洞与文档类问题被分别引导至 MSRC 与文档仓库;Bug 报告请务必填写 模板 中的“Steps to reproduce”“Actual Behavior”(必填项),崩溃类问题按模板提示附上 Feedback Hub 链接,提交后 Issue 自动带 Issue-Bug + Needs-Triage 标签进入分诊队列。
  • 被标记 Needs-Author-Feedback 时:注意 4 天(Issue)/ 7 天(PR)的 stale 预告文案,任何一次评论都会同时摘除 Needs-Author-Feedback 并避免 No-Recent-Activity,响应成本很低。
  • 提交 PR 时:按 PR 模板 填写 “Closes #xxx” 等段落;评审请求修改后 PR 会自动进入 Needs-Author-Feedback 状态,更新后标签即摘除;合并前可请维护者加 AutoMerge 标签以在门禁全绿后自动 Squash 合并。
  • 维护者视角:分诊时优先用 /dup #ID/?/feedback 等快捷指令(需 Write/Admin 权限),标签合规性由策略文件自动兜底,无需人工逐一核对 Area/Issue/Product 三元组。

小结

Windows Terminal 仓库通过 doc/bot.md 定义的标签体系,把 Issue/PR 管理收敛为一条清晰的自动化流水线:Needs-Triage 入口 → 三元组标签分诊 → Needs-Author-Feedback/Needs-Attention 双向流转 → 4+3 天(Issue)或 7+7 天(PR)的 stale 衰减关闭,辅以 /dup/feedback/? 快捷指令与 AutoMerge Squash 合并。而 resourceManagement.yml 证明这些规则不是口号,而是 23 条声明式策略(5 条定时搜索 + 18 条事件响应器)的精确实现——阅读该文件即可获得比文档更完整的触发条件与动作清单,这也是在同类大型开源项目中研究 Issue 自动化运维时最值得参考的样本。

登录后查看全文
热门项目推荐
相关项目推荐