首页
/ Flutter Issue 卫生规范:从提问、优先级到关闭的完整 Issue 生命周期管理

Flutter Issue 卫生规范:从提问、优先级到关闭的完整 Issue 生命周期管理

2026-09-06 13:03:22作者:谭伦延

Flutter 开源仓库每天产生大量 issue,如何保证每一条 issue 都"可行动、可发现"?本文基于仓库中 docs/contributing/issue_hygiene/README.md 官方规范展开,完整覆盖 issue 的提问礼仪、优先级体系(P0–P3)、标签命名约定、自动锁定机制、分配与关闭规则,并结合仓库内真实的自动化脚本(no-response.jslabeler.yml)、issue 模板(ISSUE_TEMPLATE)和分诊流程文档(docs/triage/README.md)逐条印证这些规范在工程上如何落地,读完即可掌握一套可直接用于大型开源项目的 issue 治理方法论。

一、核心理念:把每个 issue 当作"可执行的工作单元"

官方规范的 tl;dr 先给出四条最基本的行为准则:

  • 不要在 issue 下追问"进展如何",有更新团队会自己发;
  • 如果你在处理某个 bug,并且有权限,就把它指派(assign)给自己;
  • 如果你近期不会处理某个已指派的 bug,就取消指派;
  • 如果一个 issue 没有被任何人指派,可以认为它是可领取的、可供任何人处理的状态。

其背后的哲学(Issue philosophy)是:Flutter 和所有非平凡软件一样,拥有"无穷多个 bug"。issue 追踪器里记录的是社区慷慨上报的幸运清单——它包含已确认的缺陷,也包含功能请求、计划中的工作和提案(proposal)。

团队保证每条 issue 可行动、可发现的手段有三:认真打磨 issue 标题、确保每条 issue 都有复现步骤、用标签(label)对 issue 分类以便通过 GitHub 搜索找到。

补充背景:Flutter 使用三个 issue 追踪器,分别对应主仓库、flutter.dev 网站、以及 IntelliJ/Android Studio 插件。本规范主要描述主仓库的 issue 处理方式。

二、评论规范:什么话不该写在 issue 里

这是原文档篇幅最大、也最具社区治理意味的部分。

2.1 禁止 "me too" / "same" / "有更新吗" 类评论

Flutter 团队给 issue 排优先级时,会把 issue 首条评论上的 👍(thumbs-up)reaction 数量作为重要输入。因此:

  • "me too"、"same here" 这类评论只会制造干扰,让更有意义的内容更难被找到。没有新细节时,直接对 issue 点 👍;想跟踪 issue 的话,点 GitHub 界面右侧的 "Subscribe" 按钮即可。
  • 用"不修就再也不用 Flutter"之类威胁性言论催促进度,会对工程师(其中很多是志愿者)造成伤害。仓库的 CODE_OF_CONDUCT.md 明确要求避免发布没有建设性的评论。
  • 追问更新同样无益——issue 会被追问淹没,真正有用的更新反而被稀释。想追问进展,去 Discord(见 docs/contributing/Chat.md)或私聊相关人员,而不是发评论。

2.2 issue 不是所有讨论的最佳场所

issue 内的讨论应当聚焦于"这个 issue 是什么、怎么解决"。更宽泛的讨论适合放到 Discord 或设计文档(见 docs/contributing/Design-Documents.md),原因是 GitHub 的评论无法折叠组织、没有线程(threading)、通知也会淹没在其他 GitHub 邮件里。如果讨论转移到了其他工具,记得回到 issue 补充一份讨论摘要和达成的决定,让关注该 issue 的人能跟上。

同时强调两条边界:issue 从来不是求代码帮助的地方(应该去 Stack Overflow),也不是讨论项目方向的好地方

2.3 workaround 评论:点到为止

提供 workaround 对使用者有帮助,但请保持最少化,避免干扰正在修 bug 的工程师。更好的做法是指向 Stack Overflow 等更合适的场所讨论临时方案。而当 workaround 被确认存在时,应考虑给 issue 打上 workaround available 标签——这个标签正是 docs/triage/README.md 一级分诊中正式使用的状态标签之一。

2.4 不要截图贴文字

图片里的文字无法被复制、无法被 Google Translate 等自动翻译服务翻译,会让不懂该语言的团队成员无法参与。展示代码、引用他人、或展示渲染异常的字符串时,请用代码块。分享"渲染异常"的截图本身是允许的,但必须同时附上导致问题的原始字符串,方便他人粘贴进测试用例。仓库的 bug 模板 02_bug.yml 也把这一点写进了字段描述:"Please do not upload screenshots of text. Instead, use code blocks..."

2.5 提供最小化复现用例(reduced test case)

要调试问题,团队必须先能复现它。最好的帮助是:附上按照 Flutter 同款 BSD 许可证 授权的代码,并且缩减到"再删任何东西 bug 就不出现"的程度。基于法律原因,团队无法调试依赖专有代码或不可公开代码的问题。

2.6 不要粘贴未经处理的 AI 输出

原文档中相当有时代感的一节:任何人都可以把 issue URL 直接喂给 Agent,把这类输出原样贴上来一般没有价值。AI 工具可以用于完成具体任务(比如生成最小复现用例、寻找可能的重复 issue),但应作为"帮你贡献"的工具而非"替代你的贡献"——例如用 AI 生成复现用例后,你必须先确认它真的能复现再发布。同时记住"issue 里长不等于好",AI 输出往往冗长,发布前应裁剪到重点。

2.7 尽量用英文提 issue

如果你能清晰读写英文,即使问题本身与非英语有关(如某种语言文本的渲染问题),也建议用英文提 issue。其他语言也可以,但要意识到很多读者要靠自动翻译;并且避免使用非英文截图(自动翻译不处理图片文字),否则会缩小能帮你的人的范围。

三、Issue 的自动锁定(Locking)

规范说明:**Closed(已关闭)**且数周内没有任何活动的 issue 会被一个机器人自动锁定(原文档引用 .github/lock.yml 作为该配置的出处,并链接到 lock bot)。目的是鼓励开发者为新问题提交新 issue,而不是往旧 issue 里堆评论。

正常情况下不应该手动锁定 open issue。最常见的锁定理由是:该 issue 已被工程师充分理解、优先级已排定、有明确的修复路径,但持续吸引 "me too"、"什么时候修好"、"我有个可能相同也可能不同的类似 issue" 这类干扰评论。

  • 如果你担心某个被锁定的 issue 没有得到应有关注,参见下文"升级优先级"流程,或去 Chat 上联系团队。
  • 如果你有类似但不确定是否相同的 issue,可以直接提新 issue 并链回旧 issue,但请避免故意提交重复 issue。
  • 极少数情况下,issue 因讨论反复违反 Code of Conduct 而被锁定。

四、优先级体系:P0 到 P3 的精确定义

优先级是这套 issue 卫生规范的核心决策维度,原文档给出了逐级的严格定义,这里完整保留:

P0:满足以下任一条件:

  • 构建破坏(build break)、回归,或现有功能故障导致当前构建无法发布;
  • 影响团队开发速度、需要尽快解决的重要技术债;
  • 正在阻塞(或即将阻塞)顶级客户(top-tier customer)的问题(定义见下文 Customers 小节)。

P0 bug 通常少于 25 个(不足一页 GitHub 搜索结果)。如果你发现自己在给 issue 打 P0,请务必确保"提交 → 未来负责人"之间有正向交接。P0 应在数周内解决,且在 GitHub 上至少每周更新一次;正常工作日期间,P0 会在每周的 "critical triage" 会议上被审计,防止被遗忘。

P1:高优先级、位于工作清单顶端的 issue。一个 bug 在不影响顶级客户、不破坏构建的前提下,最高只能到 P1。标记 P1 的 bug 一般都在被积极处理(除非负责人正在处理 P0 或另一个 P1)。P1 应在数月内解决,至少每月更新一次。

P2:团队一致认为重要、但不在工作清单顶端。这是新 issue 的默认优先级。 P2 的 bug 可能很长时间不被修复;有些 P2 会先升到 P1 再处理,但这不是必经流程。

P3:当前认为对 Flutter 项目相对不重要的 issue(注意:这不意味着问题对"你"不重要,只是对 Flutter 本身而言不特别重要)。P3 使用 👍 数量作为讨论是否提升到 P2 及以上的信号。通常 P3 issue 会接受 PR(前提是符合 Style-guide-for-Flutter-repo.mdTree-hygiene.md 等规则)。带 would require significant investment 标签的问题可能需要比 PR 更多——例如支持一个全新平台,需要承诺 CI 资源和系统维护负责人。

4.1 "我的 bug 什么时候能修好?"

Flutter 是开源项目,贡献者(或他们的雇主)往往优先修复与自家客户相关的问题(例如 Google 工程师优先处理影响 Google 团队 app 的问题),同时也会志愿投入时间处理更通用的问题。官方给出的自查方法:

  1. 看 issue 上最近的状态更新——那是当前最可靠的信息;评论很多时,团队会尝试从首条评论链到最新状态,去看那里(但不要追问更新)。
  2. 如果 issue 带 P0/P1 标签,或已被指派,大概率会在近期被处理,只是需要时间。
  3. 否则,官方诚实的回答是:不知道,也许永远不会修。一般而言 P2 比 P3 更受重视。

相关延伸:仓库同目录下的 Popular-issues.md 不定期解释"最受欢迎 issue"(首条评论 👍 最多者)的状态,比如 Code Push / 动态加载 / 服务端渲染等社区高热问题的现状与团队的取舍理由。

4.2 升级被错误定级的 issue

  • 如果你和 Flutter 团队有联系渠道,直接找你的联系人反馈;
  • 如果没有,可以考虑寻找志同道合的开发者:组队实现、出资雇人实现,或者给 issue 点 👍 reaction;
  • 不要用评论表达你的关注——评论应保留给"推进 issue"本身。

4.3 Thumbs-up reactions 的使用规则

  • 对 issue 投票用 👍 emoji reaction;
  • 团队用 👍 数量判断 issue 的相对热度,但这只是输入之一;
  • 原文档给出的原则:Flutter 是开源项目,每个贡献者(公司)都在为自己的需求贡献;当这些需求与 Flutter 的普及方向一致时,贡献者会倾向于参考 👍 数量调整优先级;但如果你的业务依赖某功能,"最靠谱的解法是付钱让某个人去做";
  • 其他 emoji reaction 一律被忽略

五、Customers:顶级客户与特殊客户标签

Flutter 团队由多方工程师组成(专职志愿者、Google 等公司员工等),各自对"客户"的定义不同:Google 工程师视某些 Google 团队为客户,受雇开发者则有自己付钱的一方。

与团队有"特殊关系"的团队(正在协作新特性、为某活动做产品演示等)通常会获得一个 customer: ... 标签;当这些客户与团队成员紧密协作时,他们可被视为"顶级客户"用于优先级决策,P0 有时就是为影响顶级客户的 bug 保留的。

原文档还包含两个实践细节,值得保留:

跨 bug 系统协作:有些客户有自己的 bug 系统跟踪 Flutter 问题。GitHub issue 列表是唯一权威(canonical)来源;但只要你方 issue 链向客户侧 issue、且你方被授权访问,团队会跟随链接去跟踪,甚至可能在那边沟通。

特殊客户标签

  • customer: product:把产品经理和高层领导希望解决的问题送到对应工程团队面前;
  • customer: crowd:代表影响大量人群的 bug。初期分诊(见 docs/triage/README.md)中,高曝光度 bug 会被这样标记以引起工程团队注意。"大量"是判断性的:几十个人独立撞到同一问题且最终被判定为重复,是好候选;反之,如果存在"动员大家去评论某 bug"的活动,那很可能不构成合法的 customer: crowd——人们通常不需要被动员就会自然报 bug;
  • 原文档一句颇为犀利的收尾:一个 bug 只有坏到"足以让大批人考虑转行"时,才应该被标记为 customer: crowd + P0

另一个值得注意的标签是 blocked:表示某个 issue 在另一个问题解决前无法推进,尤其适合用"自己的已指派 issue 列表"驱动工作的人。

六、标签系统:命名约定与自动化

Flutter 仓库使用大量标签,原文档列出的命名约定(naming conventions)完整如下:

前缀 / 形式 含义
a: * "area",跨 Flutter 实现层级的特定主题(如 accessibility、text input)
browser: * Web 版 Flutter 的浏览器专属问题
c: * "category",bug 的种类(regression、crash、new feature request 等)
d: *(紫色) "devtools",开发者工具问题
d: *(绿色) "documentation",文档相关问题(与前一类共用前缀、以颜色区分)
dependency: * 被上游项目(如 Skia、Dart)阻塞
e: * "engine",Flutter 引擎子集(对应仓库的 engine 目录)
f: * "framework",Flutter 框架子集(对应 packages/flutter
found in release: x.yy issue 在哪个 Flutter 版本被发现
from: * issue 的来源(如 research、postmortems),非自然上报时
t: * "tool",Flutter 工具子集(对应 packages/flutter_tools
p: * "package",具体包(浅青色为包,深青色为插件)
platform-* 一个或多个平台特有的 bug
r: * "resolution",issue 被关闭的原因

添加标签的自由度与纪律:标签"或多或少是免费的",添加很方便,但请先告知团队成员(至少在隐藏频道上提一句)以便获得反馈;新标签必须遵循一致的颜色与命名体系(例如所有 framework 相关标签都是蓝色且以 f: 开头)。标签应为 bug 增加信息量——如果你想用标签"搜出所有某主题实例",请记住:无法强制所有人打标签,但可以依赖自动化。

这一"依赖自动化"的论断在仓库里有直接证据:.github/labeler.yml 是一份基于 GitHub Actions labeler 的配置,按改动文件的 glob 模式自动给 PR 打标签,例如:

'a: accessibility':
  - changed-files:
    - any-glob-to-any-file:
      - '**/accessibility/*'
      - '**/*accessibility*'
      - '**/semantics/*'
      - '**/*semantics*'

docs/triage/README.md 中"我们有一条脚本给所有影响 framework 的 PR 自动打标签"的说法,正是这类机制的运作方式。此外,仓库的 .github/ISSUE_TEMPLATE/ 目录提供了从激活确认(01_activation.yml)、bug 报告(02_bug.yml)到功能请求、性能问题、基础设施、设计文档(07_design_doc.yml)、一方包、Wasm 在内的十余种结构化模板;模板中 config.yml 甚至直接配置了 "I want help writing my application → Stack Overflow" 的引导链接,从源头把"求助类内容"挡在 issue 之外——这正是前述"issue 不是求帮助场所"的机制化落地。

Milestones:规范明确声明——不使用 GitHub milestones 来跟踪工作。

七、Issue 指派:self-assign 与 "licking the cookie"

原文档的指派规则可以归纳为:

  • issue 通常自我指派。只在他人明确自愿处理时,才把 bug 指派给别人;没有权限指派自己的 issue 也不影响提交 PR(见 Tree-hygiene.md)。
  • 只在"正在处理"或"已排期处理"时才把 bug 指派给自己;不知道何时处理就留空(unassigned)。
  • 不要随意把 bug 指派给别人,除非你知道对方会处理;发现自己名下有"没有排期"的 bug,就取消指派,让别人敢于接手。
  • 反之,正在做或已排期且确信会做,就应该指派给自己——这是团队了解事情进展、避免两人同时修同一问题的方式。

团队内部用语"licking the cookie(舔饼干)"形象地描述了这件事:把 bug 指派给自己相当于告诉别人"这个别碰";如果你之后不做了,就像把饼干舔了一遍让人不想吃、自己却又不吃。"unlicking the cookie" 就是向团队表明你其实不做了——比如取消自我指派。

另有一条"团队成员个人 bug"的实践:需要跟踪某项工作时,可以提一个 bug 并自我指派。这类自我指派的"伞形 bug"基本会被机器人忽略,也可以忽略针对它们的规则(离职时这些 issue 通常会被关闭)。也可以用 GitHub Projects 管理工作项。

八、"什么都要提 bug"及其例外

原文档的主张是:File bugs for everything——遇到任何需要做的事情都提 bug;实现某功能时如果知道没做完,就把没做完的部分提 bug,这样团队始终清楚还欠什么。

8.1 例外:两类不该提的 bug

  • 元问题(meta-questions),例如"为什么 bug #XYZ 被关闭了?"——应回到原 issue 评论,或提出仍未解决的实际问题;
  • 故意重复,例如"这和 bug #ABC 一样,只是那边没得到足够关注"——应该给原 issue 点 👍、补充新细节,或最好的做法:直接指派给自己开始做。

8.2 提出具体变更的四步推荐流程

  1. 提一个 bug 描述问题(仓库提供 03_feature_request.yml 等模板);
  2. 写一份引用该问题并描述方案的设计文档
  3. 在 bug 下和 Chat 上推广该设计,收集多方反馈;
  4. 反馈大体正面后,实现它并提交 PR——提交 PR 的细节见 Tree-hygiene.md

8.3 每个 issue 都应可行动(actionable)

  • 避免在模糊主题上提 issue 而缺少清晰的问题描述;
  • 请关闭不可行动的 issue(详见 docs/triage/README.md);
  • 每个 issue 都应有清晰的复现步骤、预期结果与实际结果。缺少这些信息时向报告者索取;不补交则关闭。

这一点同样被机制化:bug 模板 02_bug.ymlSteps to reproduceExpected resultsActual resultsCode sampleFlutter Doctor output 全部是 required: true 必填字段,Code sample 字段甚至写明"没有它我们不太可能推进这个 issue,只好遗憾地关闭它"。

九、关闭 issue:正当理由、错误理由与"绝不能关"清单

原文档给出了三段式判断框架,信息量很大,值得完整继承。

应当关闭的情况

  • 修复了;
  • 是重复(duplicate,见 docs/triage/README.md 的 Duplicates 一节);
  • 一个 issue 里塞了多个可独立处理的请求——应建议拆分成独立 bug;
  • 描述的是"解决方案"而非"问题"(例如没有用例、用例不显然、可能存在其他方案);
  • 不可行动且没有异常症状(invalid、无复现步骤、已失效、描述不清且报告者不补充等);也包括只有原始报告者能复现的非灾难性 bug——建议报告者自行调试(可给出插桩建议)、邀请其加入 Discord 求助,然后打 waiting for response 标签,数周不回复会自动关闭;
  • 不太可能解决的、即使解决也不属于核心 SDK(例如会落在某个 package 里)的功能请求——带 would be a good package + P3 标签的清单是"不修直接关"的好候选;
  • 即使有人提交修复也不会接受的 issue(例如 docs/about/Values.md 中"Levels of support"为 4 级、完全不接收补丁的平台支持请求);
  • 关于内部流程、工具或基础设施(用户不受影响)、且团队没有计划处理的 issue(如会标 P3 的 c: tech-debt 项);
  • 跟踪技术债,但所提改进收益甚微,或需要大量研究才能评估的——更合适的做法是让熟悉该代码的人基于自身判断改进。

关闭 issue 的糟糕理由

  • "长时间没更新"——问题没变化时不更新很正常;
  • "是低优先级的用户可见问题"——团队宁愿有一个长期开放的 bug 承载一段完整对话,也不愿有多个短命关闭的 bug 各含一段孤立对话;
  • "修起来很难"。

具有以下特征的 bug 一定不能关闭

  • 描述清楚、能稳定复现的问题;
  • 论证充分、有坚实用例和明确目标、且合理地无法用 package 实现的功能请求(如果基本不会做,应标 P3 而不是关闭);
  • 跟踪技术债且改进明确可行动、收益清晰;
  • 请求为 Material widget 增加定制、且该定制干净地契合现有 Material 设计库精神;
  • 由团队成员提交并指派给该成员本人的 issue。

9.1 "waiting for response" 的自动关闭在仓库中如何运作

规范中"数周不回复则自动关闭"不是口号,仓库内的 no-response.js 就是执行者:一个 GitHub Actions 脚本,查找所有带 waiting for response 标签的 open issue/PR,从 timeline 事件中定位打标签的时间点(兼容旧标签名 waiting for customer response),检查打标签之后作者是否有回应;若 daysUntilClose = 21 天内无回应,就自动关闭 issue 并留下标准留言:

"Without additional information, we are unfortunately not sure how to resolve this issue. We are therefore reluctantly going to close this bug for now. If you find this problem please file a new issue with the same description, what happens, logs and the output of 'flutter doctor -v'..."

docs/triage/README.md 的一级分诊流程则规定了何时该打这个标签:报告不清晰、复现步骤不足时,礼貌地索取信息 + 打 waiting for response;此前已索取过、报告者仍无法让 bug 可行动时,视对报告者后续能力的判断"道歉后关闭"或打标签等 21 天。两篇文档一"流程"一"执行",闭环完整。

十、Flaky Tests 的 issue 处理约定

当测试出现 flake(不稳定失败),机器人会自动提一个带 team: flakes 标签的 P0 bug。规范要求:

  • 该 issue 应被尽快调查,并随后赋予一个明确的优先级;
  • 任一时刻,"最 flaky 的测试"应保持 P0;难以定位的 flake 可以降级(如 P1),但绝不能被完全忽略
  • 修复后(即使"莫名其妙好了")务必把 bug 关闭。

更深入的机制(如何从 dashboard 识别 flake、如何在 DeviceLab 测试中预防、bringup 流程等)见 docs/infra/Reducing-Test-Flakiness.md

十一、小结:一套可复用的 issue 治理方法论

把上述规范连起来看,Flutter 的 issue 卫生实际上是一套环环相扣的机制:结构化模板(ISSUE_TEMPLATE)在入口保证信息完整;两级分诊(docs/triage/README.md 的 primary/secondary triage)在 1–2 个工作日内完成路由;标签命名约定 + 自动化(labeler.yml)保证可发现性;P0–P3 优先级 + 每周 critical triage 审计保证注意力分配;👍 而非评论表达热度;waiting for response + no-response.js 清理僵尸 issue;lock bot 封存陈旧话题。对任何管理大规模 issue 追踪器的开源团队来说,这套"礼仪规则 + 自动化执行"的组合都值得逐条对照参考。

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

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.13 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
897
5.8 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
529
593
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
916
1.83 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.58 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.35 K
1.46 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.01 K
515
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
547
388