我听过不少人凭借爱好开源了自己的项目后, 却对 issue 太乱感到困扰, 甚至想干脆直接禁用 issue. 事实上, 任何项目达到一定规模后, 如果不对 issue 进行适当管理, 都会使 issue 信噪比过低, 失去原本的功能.
这篇文章主要从 maintainer 的角度说说, 在具备规模的项目中管理 issue 的一些方法和原则.
任何具备一定规模的项目都应该使用 issue template.Issue template 位于项目的.github/ISSUE_TEMPLATE
目录, 包含两种文件:
每个 template 有一个 markdown 文件, 对应一类 issue. 其中描述需要用户提供的信息.
还可以为这个 issue template 自动配置 issue label. 然而由于 template 是用户选择的, 这种方式得到的 issue label 噪音较大, 可能还需要 maintainer 纠正. (我的策略是仅对 "feature request" 和 "documentation issue" 自动 label)
可选的config.yml
全局配置文件. 有用的配置包括:
blank_issues_enabled
: 是否允许用户不使用 template 自己写 issue.contact_links
: maintainer 用它将用户引导到其他地方 (论坛, discussions 等).Github 近期在测试 issue form, 是 issue template 的升级版, 有了更好看的 UI 和丰富的输入类型. 可惜我一直还没有测试机会.
常见的 issue 有如下两大类:
除了这些之外, 用户常常还想问各种其他问题, 譬如 "怎么用 XXX", "我这样做对不对", "项目里这段 code 是干嘛用的" 等等. 暂且将它们称为 "question". 我认为, 大的 (issue 很多的) 开源项目中 issue 里不应包含这些 "question", issue 应当 不超过上面的两类.
为什么? 当 issue 很多的时候, "question" 与两大类 "issue" 有些本质的不同, 会导致 issue 难以管理:
总而言之, question 大多以用户为中心, 处理它们的沟通成本更高, 而对项目的 contribution 却更低. 混杂在以项目为中心的另两类更重要的 issue 中会分散 maintainer 的精力. 因此很多大的项目都希望将 question 剥离出 issue.
然而, 用户确实有问问题或进行其他交流的需求, 这样的需求可以用 github discussions / 论坛来满足.
Github 近两年推出了 "discussions" 版块.Discussions 在功能 / UI 上与 issues 有所区别, 各方面都更像传统的论坛: 例如没有 open/close/assign 的状态, 可以 "顶帖", 可以 "mark as answer", 等等. 简单来说, github discussions 就是提供一个 简化版的论坛.
在内容上, github 并没有给 discussions 和 issues 定义明确的边界, 这个边界由每个项目自己定义:Maintainer 应通过 issue category 和 issue template 来 声明自己愿意支持解决的 issue 有哪些 (例如 bug report, feature request), 并告知用户 "其他" 讨论 / Question 可以发到 discussions 中. 如果发错了地方, maintainer 可以通过 github 提供的按钮一键在 issue/discussion 之间转换.
我们以 PyTorch 为例. 在 PyTorch 的 issue 列表点击 "new issue" 后, 进入 PyTorch 的 issue 类别 页面.
可以看到:
PyTorch issue 就只包含上文提到的两大类: bug 与 feature (只是细分成了更多类).
实践上把 documentation 细分出一类是很有用的. 因为 documentation 的勘误到底是属于 "bug" 还是 "enhancement" 可能会有歧义.Documentation 被细分后, maintainer 就可以将 "bug" 定义为狭义的代码 bug, 将 "enhancement" 定义为 "feature request", 使得类别的定义更清晰.
所有 "其他讨论" 都通过最后一行的按钮被引导到 PyTorch 的官方 Discourse 论坛上. 曾经, PyTorch 甚至专门有一个 "question" issue template 的内容就是 "不要发 question, 请用论坛". 由于避免了 question, PyTorch issue 始终维持了高质量的技术讨论, 也达到了管理开发任务的 "tracker" 功能.
Github discussions 的定位就是一个项目自带的简易论坛, 毕竟不是所有项目都有资源自己搭建一个论坛.
再以 TensorFlow 做个反面教材: 我由于曾经是深度 TF1 用户, 在早期还是很喜欢看它的 github. 然而 TensorFlow 长期没有对 issue 进行分流. 可以观察到大约在 18 年前后, 估计由于 issue 的噪声太大, 性价比太低, TensorFlow issues 里已经很少再有 core developer 回复, 导致真正有价值的 issue 也更难以得到重视了. 我就多次需要靠手动 at 对应领域我认识的 developer 才能有人回应我报的 bug. 直到 2021 年, TensorFlow 才终于开始在 issue template 里把用户引导至自建 Discourse 论坛.
最后还是要提醒: discussions / 论坛仅适用于规模较大, 问题较多的项目. 对小项目, 额外一个讨论平台引入的 overhead 可能得不偿失.
在第一篇文章中说到,maintainer 自己决定自己有哪些义务, 决定自己的 commitment, 也即自己愿意对用户提供哪些 "support". 很多 maintainer 与用户沟通上的问题, 源于没有划清自己的义务范围. 一旦这条线划清了, maintainer 就无需为乱七八糟的 issue 头疼: 项目不 support 的问题不必操心, 关闭或者移至 discussions 都可以.
Maintainer 应该通过 issue template 的选项表明哪些类 issue 是允许的. 可以通过blank_issues_enabled: false
来禁用 "无 template" 的 issue. 可以通过contact_links
引导 "其他问题" 到别的地方. 如果用户依然发了不支持的 issue, 可以以 "不支持" 为由关闭 / 移至 discussions.
Issue template 的内容里可以更清楚的声明哪些常见情形是不支持的, 例如:
用户应该认识到 "支持 / support" 到底是什么意思:
对于 maintainer 职责之外的 issue, 即使 maintainer 个人愿意帮助, 也可以立刻关闭 / 移至 discussion, 再进行评论. 这样的情况下, 我一般会关闭 issue 并说:
Because of ABC, this issue is unsupported/unrelated, therefore closing the issue.
I think doing XYZ might solve/help the issue.
在这里, "close issue" 表明了 issue 不被支持, 这样提前避免用户由于 "得到了评论" 而对于 support 有不切实际的预期. 也避免了 (其他) maintainer 在下次处理 issue 列表时再看一次.
同时, 也在不需要花自己太多时间的前提下给了简单的建议, 但至于是否能解决问题我就不再管了.
这一节说说对于 bugs/unexpected issues 的常见处理流程和注意事项.
使用 Issue Template: 上篇文章中说了用户报告 unexpected issues 时需要提供的几类信息: expectation, unexpected observation, environment, reproducible example.Maintainer 应该使用 issue template 来告知 / 引导用户提供这些信息.
Detectron2 的 "unexpected problems" issue template 可以作为参考. Facebook AI Research 的其他一些 project 也参考了这个 template (如 pytorch3d,vissl).
检查必要的信息: 还是有不少用户不尊重 issue template, 不提供需要的信息. 以下几个方案可能有帮助:
If you need help to solve an unexpected issue you observed, please include details following theXXX issue template (link).
分析, 解决 issue: 任何一个有足够信息的 unexpected issue, 应该有且仅有如下几种结果:
可以看到, 以上几种结果基本都是对项目有 contribution 的. 甚至即使 issue 最终不存在, maintainer 也可能从 unexpected issues 中看到提升用户体验的机会. 因此 unexpected issues / bugs 对项目有很大价值.
介绍一些管理 issue 的 bot:
上面提到过的检查 issue 是否包含必要信息的 bot. 然而为了用户体验, 这个 bot 是 precision-driven 的, 只检测最明显的情况, recall 并不高.
自动关闭 "needs-more-info" 的 issue: 如果 issue 有了 "needs-more-info" 的标签, 等待用户提供必要的信息, 却长时间没有 update, 就会被 bot 自动关闭. 当有了 update 时, 标签会被这个 workflow 自动移除.
自动锁定古老 issue: 如果项目一直在活跃开发, 那么一个古老的, 已解决的 bug 很可能没有任何值得 follow up 的信息: 即使类似的 bug 又出现了, 大概率也和旧的 bug 没什么关系. 那么可以对此类 issue 设定为静默一年后自动锁定 (禁止评论).
自动 label:Github 支持按照 issue template 来自动 label, 但是那样的粒度太粗. 如果对于特定类的 issue 能够根据内容来精准匹配的话, 也可以用这个 bot 添加 label. 但是需要注意自然语言处理是很困难的, 给这个 bot 写规则并不容易.
自动订阅 label: 巨型项目中, 开发者想要自动 subscribe 特定模块相关的 issue. 这个 bot 按照 issue 的 label 自动添加 "@username" 来 subscribe 感兴趣的开发者.
Stale bot: 自动关闭一段时间没有 activity 的 issue. 这个 bot 很常见, 但 不应该被使用, 因为没有 activity 不代表 issue 解决了. 参考:
注意这里假设了 issue 和 question 是被区分开的. 如果 question 也被包括在 issue 里, 自动关闭 question 是可以接受的.