开篇:大家为什么都在玩开源?

近年来,不仅是个人开发者,国内的企业也在以肉眼可见的速度参与开源,热衷于提升在开源领域的影响力,尤其是这两年在国家政策的推动下,开源浪潮在国内达到了前所未有的盛况。

个人开源的原因比较多,我简单列几个:

  1. 结识志同道合的开发者和领域专家
  2. 通过参与开源提升个人影响力
  3. 为自己职业经历增加闪光点
  4. 尝试通过开源获利
  5. 没什么特别的理由,就是玩儿,爱折腾

而企业做开源的目的性更强,我认为不外乎三个方面:

  1. 为了得到更多的反馈,用社会化协作的力量进行同行评审,提升质量并反哺企业,还能达到降本增效的目的
  2. 为了提升业界技术影响力,吸引高端技术人才的目光,招揽人才
  3. 为了发现更多的商业机会实现商业价值

不过,对于企业从内源到外源,是无法完全复制企业内源那套玩法的,虽然二者有很多共性,但毕竟参与者从企业内部员工直接扩大到了整个社会,在协作方面还是有不少差异的。从 Gitee 建立至今,我有幸见证了非常多开源项目的成长如 JFinalFurion 等优秀的个人项目,近两年也参与了不少 Huawei 在 Gitee 上发布开源项目的大事件,比如 openEuler、Mindspore、OpenHarmony 等。

本文是基于我对 Huawei 在 Gitee 上开源项目协作方式的观察,来分享下开源软件协作上的一些优秀实践,对于企业参与开源的相关事项如开源软件引入评审、内部开源治理、对外开源审计、代码准入准出、后期运营等,在这里不做过多的介绍,感兴趣的可以参阅前不久 GOTC 会上的主题以及《开源指北》:

后续如果有时间也会整理一下自己对企业内外部开源治理的一些理解,如果有特别想要了解的,欢迎留言给我一起学习研讨。

好了,下面进入正题,我把开源软件协作中一些必要的项整理出了一张图,接下来我们来围绕着此图进行展开介绍:

图中各项限于篇幅并基于个人理解有所精简,如有遗漏,望请谅解~

输入图片说明

建立共识

在我们准备推出自己的开源项目的时候,我们需要首先考虑的就是如何建立共识,除了完善我们的代码结构以及相关注释,面向不同受众的文档也不可少。建立共识不是一句空话,不是一句口号,需要我们从不同的角度出发,讲明白开源项目的用途和作用、做好各项规章制度、定好具体的行为准则。

1. README

相信大家在浏览一个开源项目的时候,首要去看的就是这个项目的 README,一个项目的 README 就是这个项目的简历,不仅决定了用户对项目的第一印象,更决定了用户是否会继续看下去,如果 README 写的不好,很可能就会丢失不少目标用户。

README 文件首先就是要有一个简单明了的概括性的介绍,并且需要分析开源项目所面向的不同用户的需求,来提供不同的目录入口,让用户能够快速进入。

输入图片说明

这里以 OpenHarmony 的 README 为例,给出了简短的介绍以及远景,并且给出了一些快速跳转,方便不同的人进到自己关心的内容,比如有想要来下载代码的,有想要了解技术架构的,有想要看看怎么参与的,还给海外用户留了英文版本的快速入口等。

在 Gitee 上你可以建立README_CN.mdREADME.md,Gitee 会根据访客的浏览器语言来自动的选择默认展示的 README

OpenHarmony 的 README 是比较有参考价值的,可以看的出来是经过了精心的设计的。我们需要能够分析我们的受众,并且从不同的受众的角度出发,给到他们想要 Get 的信息,才能更好的留住每一位用户。

相反,有一些开源项目上来就是一张大大的 Logo,在用户浏览第一屏的时候,把那些有用的信息全都挤下去了,根本 Get 不到重点,可能就直接关闭浏览器标签了。当然,不排除一些有历史、有口碑的开源项目这么玩,但是现在这个时代,酒香也怕巷子深,多体现些有价值的信息自然是好的。

2. 完善的文档(Doc)

上面说到的 README 可以说是开放给用户的一个门面,能快速的引起用户的注意,提起用户的兴趣,但是能不能让用户进来买单,就要看项目到底有多少东西了。

我们可能把代码结构以及注释做的非常好,但是无论是哪种类型的用户,都不会上来就直接抡代码的,他们会通过文档进一步了解项目,文档其实就是体现项目价值的柜台,当用户看到豪华的门面装饰进来后,他们更在意的是柜台摆放了什么东西,所以文档内容如何组织,如何体现,也需要深思熟虑。

一般来讲,文档根据受众的不同分为两种,这里以产品型的开源项目为例,会有产品文档以及开发者文档。除了内容的丰富性,文档的可浏览性以及易搜索性也需要兼顾,毕竟谁也不想找一个东西的时候要人肉遍历,对吧?

3. 开源协议(LICENSE)

开源协议的重要性不言而喻,与开源软件有关的开源协议纠纷也时常爆出。所以,为自己的开源项目选择一个合适的开源协议就非常重要了。

常见开源协议的介绍:https://opensource.org/licenses/alphabetical

开源协议种类繁杂,理解起来相当费劲,如果你对开源协议不了解,可以使用 Gitee 提供的开源许可证选择工具,一步一步进行 LICENSE 的选择:

输入图片说明

当然,你也可以选择自己去写 LICENSE 内容,这比较费脑,没有什么好想法的话,还是选择先从现有的协议进行选择比较好。

4. DCO 协议

DCO 全称是 Developer Certificate Of Origin,这个协议最初是 Linux Foundation 发起的,OpenHarmony 在它的 docs 项目引入了这个协议:

https://gitee.com/openharmony/docs/blob/master/DCO.txt

上面贴出的链接已经由开放原子开源基金会给出了翻译,你可以看看。这个协议顾名思义,存在的目的就是为了免责,防止开发者拿其它有版权限制的代码做提交贡献,从而给项目带来法律问题,或者说在不久的以后带来问题。

另外还有一个 CLA 协议,个人觉得这个协议比较麻烦,需要贡献者自行确认协议明细,后续的章节我们会详细介绍到如何做 CLA 的签署,如果你想了解 CLA 和 DCO 的差别,你可以访问下面的链接:

https://opensource.com/article/18/3/cla-vs-dco-whats-difference

5. 贡献者指南(CONTRIBUTING)

做开源的最重要的目的之一就是接受来自社会的代码贡献,所以有一个贡献者指南给到那些乐意参与进来的开发者还是非常有必要的,这不仅可以使贡献者快速融入,也能够建立起贡献的流程和规范,能够免去非常多不必要的沟通成本。

这里我们可以参照下 MindSpore 的 CONTRIBUTING 和 OpenHarmony 的 参与贡献.md ,主要有以下一些内容:

  • 如何签署 CLA(贡献者许可协议)
  • 社区行为准则(CODE_OF_CONCEPT)
  • 如何参与 SIG 兴趣小组
  • 如何贡献代码和文档
  • 沟通和交流的方式
  • 贡献的具体流程是如何的
  • 前后端代码规范、前端样式规范
  • 如何反馈 Bug 和 建议 (反馈也是一种贡献:D)

可以看到这简直就是《新生入学指引手册V5.8.7》,保姆级的贡献者指南有助于让开发者更加快速的融入,丰富而健全的指南能够减少让开发者知难而退的概率。要知道,增加一个 Pull Request 的贡献可比增加 100 Star 要难多了,对于有意向的贡献者,我们应当牟足劲为他们提供一个友好的环境。

小结

除了上面提到的5点建立共识的方式,在开源社区也有很多其它的方式,它们解决的都是某一场景下的具体问题,对齐信息传递共识,比如NOTICESECURITYCHANGELOG等等,这里不再赘述,可以前往开源项目自行查阅。

无论哪种方式,我们的目的都是能够减少开源项目在协作过程中的沟通成本,尽可能的使行为乃至公共词汇保持一致,这样能够减少歧义,减少实际协作过程中的偏差,提升整体协作的效率和产出。

协作管理

有了一定的制度、准则之后,我们就可以开始推动开源项目的运作了,在整个运作的过程中,最最最重要的就是协作的管理了,毕竟我们要做的是开源项目的「协作」,所以无论是任务、Bug 还是代码,都需要人的参与,那就需要我们进行一些必要的协作管理方式。

职能小组

职能小组也可以叫做兴趣小组,在一个开源项目内,由于会涉及到不同的子模块或者子项目,甚至于一些特殊的领域划分比如前端、后端、UI、测试等等,所以通常的做法是专业的人聚集到一块做专业的事。

在 OpenHarmony 社区里面叫做 SIG(Special Interest Group)特别兴趣小组,SIG 有完善的管理章程,从建立、加入、维护等都有非常详细的规章制度,给 OpenHarmony 开源项目的参与者提供了一个能够专注的小组,让每个人都能在自己所长的领域贡献力量。

输入图片说明

除了 OpenHarmony 的 SIG,还有不少其它的开源项目也有类似的兴趣小组,有的是以 Group 的形式存在,有的是以虚拟组织的形式存在,比如把一个项目划分为不同的子项目,然后不同的人参与。共同点就是将项目的某一模块单独的由一部分人来负责,这部分后续产生的评审、提案等均需要相关模块的人参与进来。

多仓库管理工具推荐:

  • Git Submodule
  • Repo
  • Jiri

缺陷管理

运营一个开源项目最重要的目的就是接收反馈,所以对于反馈的管理措施是否健全也直接影响着项目的好评度。试想,一个用户提了一个非常严重的 Bug,但是好几天了都没有人搭理,并且也没有具体的上升通道,那岂不是凉凉?

所以说反馈管理最重要的一件事情就是:统一反馈渠道。我们可以建立 QQ 群,也可以建立微信群,也可以建立 Slack,可以建立非常多的即时通讯的方式,但是即时通讯最大的问题就是没法积累。我们必须要有一个可以留存的统一反馈管理方式,一方面是可以集中的发现和响应问题,二是可以积累作为知识库,一般情况下都是使用代码托管平台提供的 Issue 工单系统来进行管理:

输入图片说明

上图是 openharmony/kernel_liteos_a 在 Gitee 上的工单管理系统,在一个位置统一管理工单能给我们免去不少麻烦,所以无论是在邮件,还是在即时通讯群,当有一个问题无法快速处理,或者说它是一个需要长期跟进的工作的事情,请在 Issue 开个工单保持跟进吧!

意见管理

上面我们讲到,如果用户有反馈,我们应该及时响应,并且快速修复。这里提到的是针对缺陷类别的反馈,但是除了缺陷、使用等之类的常规反馈外,我们也会经常接到不少非常有建设性意见的 Issue,那么对于这些 Issue,我们该如何跟进呢?

毫无疑问的是,这些意见型 Issue 直接的推动了开源项目的发展,这种 Issue 可能会引起不少的讨论,并且对于这些讨论我们需要有一个明确的结论,并且在讨论过程中产生的任何有价值的信息都应该被汇总记录。举个例子,比如我们有一个功能是某个 Issue 中经过讨论一步一步延伸出来的,那么我们应该在文档处或者项目处记录:

  • 这个功能当初在哪里提出来的?
  • 中间经过了什么样的讨论?
  • 以上的这些过程相关的 Issue 或者讨论的链接是哪些?
  • 最终实现这个需求的 Pull Request 是哪个?
  • 后续还有哪些 TODO?

这样不仅能够完整的为后来的贡献者提供完整的上下文,也有助于提升贡献者的参与感。

PMC 项目管理委员会

有了一些优秀的意见,或者有了一些不错的想法,我们一般情况下是可以直接去认领这些 Issue 然后直接开工的,但是对于一些管理方式更加严谨的开源社区来说,如果你想要参与开源项目的贡献,你需要先提案,通过了项目管理委员会的评审之后,你才可以继续进行代码的编写,否则就有可能会做无用功。

项目管理委员会一般会分为两种形式来对这些提案进行评审,产品决策委员会和技术决策委员会,产品决策委员会主要是从产品层面来决定这个提案是否符合项目发展的预期,是否契合项目发展的路线;而技术决策委员会则对产品实现的技术方案进行评审,对它的实现方案的合理性进行决策。

除此之外,PMC 也全权负责社区中其它的事项,并且会定期开会,一些比较 Open 的 开源社区的 PMC 甚至会把会议纪要甚至会议直接公开出来,具体 PMC 的推进形式可以参照 OpenHarmony 或者 Apache PMC

代码提交

在一位开发者了解了上诉所有流程,并且基于一个社区共同认可开始进行代码的编写的时候,我们就进入了代码提交的阶段,这里所谓的代码提交并不是通俗意义上的提交,而是在开发者开始编码的那一刻,这个过程就开始了。

我们在这个阶段需要花费更大的力气来为开发者保驾护航,把一切能够自动化的全部自动化,把一切能够自助化的全部自助化,并且尽可能将这些自动化的验证左移,一方面是为了尽早发现问题,另一方面是为了减少问题的累加导致的更大的问题。

代码规范

代码规范可以说是任何一个项目的最基本的要求,没有了代码规范,整个项目的代码就如同多国语言混杂一样,没有一个人可以通篇看懂。建立代码规范的目的还是为了统一共识,这跟我们前面讲到的项目层面的共识是一致的,都是为了减少沟通成本和规范行为。

开源项目会在其贡献者说明或者文档中写明本项目的代码规范要求,这些代码规范要求不仅仅是代码,还有文档、测试脚本等,一般情况下有如下一些:

  • 代码(项目涉及到的不同语言的代码
  • 测试(不同测试框架
  • 文档(提交文档贡献遵循的格式
  • 翻译(如果要参与翻译,正确的表述格式应该如何做
  • 数据库(数据库的迁移脚本格式

这里可以参见 MindSpore 的 CONTRIBUTING.md

除了书面化要求,我们也应当进一步的去设置一些自动化的步骤,来帮助我们的开发者进行这方面的检查,比如在提交 Pull Request 后,设置一些流水线门禁来进行代码规范的检查,但是这些步骤完全可以放到用户本地来预先执行的。

比如要求开发者安装 IDE 的格式检查,或者要求开发者在提交代码之前跑一些代码格式扫描的工具,但这些要求太过于繁琐,开发者不一定喜欢,他们更喜欢的是专注代码而不是其他繁琐的细节,所以我们可以使用一些版本控制的工具进行,比如 Git 的钩子。

这里推荐一个工具 leftbook,能够协助我们快速管理和应用我们想要的钩子,并且在不同语言下可以通过一条命令自动的帮开发者安装这些本地的钩子,这些钩子顾名思义就是在进行某一些操作的时候自动前置或者后置出发的一些脚本。

比如 Gitlab 就是用的这个工具结合 Rubocop 来进行 Ruby 代码规范的检查,开发者如果本地编写的代码不符合规范,那么在进行 Commit 前问题就会被抛出,只有解决了这些问题才能继续进行提交:

输入图片说明

当然,我们选择或者自定义的这些工具,不仅可以发现问题,最好还应该能够在不改变代码逻辑的前提下,自动的帮开发者规整问题。

提交流程

当开发者完成了本地所有的工作之后,大部分的开源项目的提交流程都是要求在对应的仓库里面提交 PR/MR 的。为什么要说大部分呢,因为有一部分开源项目并不是这种形式,比如 Git,依旧是通过邮件 Patch 的方式进行代码的贡献。

这里为什么要把提交流程也单独拎出来说呢,我把代码提交上去,然后创建一个 PR 不就完事了吗?

No.

就像提问题需要描述清楚问题背景一样,提交 PR 也需要开发者能够描述清楚自己做的改动可能的影响,或者说有一些开发者不会注意到的问题需要我我们进行提示。比如大部分开发者认为代码完成就是完成了,他们的 DOD 和我们要求的完全不一致,那如何才能保持一致呢?

除了上面我们提到的需要写清楚贡献者指南,我们还需要进行一些必要的二次确认或者自动化确认,因为我们不能完全假定开发者一定是看过了所有的文档,并且完全按照要求进行的。为失败而设计,这个理念并不只适用于架构、产品,所有与外界有交互的场景均适用。

这里我们参考 OpenHarmony 的一个子项目的做法,他们使用了 Gitee 提供的模版功能,也就是在仓库根目录下的.gitee文件夹,设置一些指定文件名的文件,这些文件的内容在开发者提交 Issue 或者 PR 的时候就会当作默认的模版展示出来:

输入图片说明

当然,除了这些,我们还可以设置一些 TODO 让用户一个一个确认:

  • 添加了足够的测试了吗?
  • 如果是一些功能性的更新,需要补充文档,你补充了吗?
  • 功能性的更新需要添加 CHANGELOG 入口,你添加了吗?

总之,我们需要在开发者提交之前,让开发者确认好各个细节,这样能够避免后续各种无效的沟通成本,这就是延续之前建立共识的做法。

CLA 签署

前面我们也提到,CLA 的签署不同于 DCO,我们可以把 DCO 看作是一种特殊的 CLA,一种通用的、标准的贡献者许可协议。

但是对于一些开源项目,DCO 无法完全满足需求,那么就需要我们自定义一些 CLA 并由开发者确认签署,这个过程在华为的开源项目中做法:

  • openEuler、MindSpore 通过在线 CLA 平台签署:https://clasign.osinfra.cn/
  • OpenHarmony 通过在线 DCO 平台签署:https://dco.openharmony.io/ (OpenHarmony 之前的方式是通过邮件进行发送确认)

这个检测的状态会作为一个门禁,如果未签署,也就是门禁不通过,那么后续的步骤就不会再进行:

输入图片说明

相反,如果通过了,则就进入正常的流水线门禁流程。

单独把 CLA 签署门禁提出来是因为它无论是对企业开源项目还是个人开源项目来说,都非常重要,为了避免后期产生的版权争议,这一步最好不要免去。

质量门禁

质量门禁这一步需要投入大量工作,将前期约定好的所有规则通过工程实践落地。前面我们也说过,能自动化的全都要自动化,所以门禁之所以叫门禁,是因为它是代码入库的最后一道门槛,我们需要完整的去自动化检测所有的项目,包括但不限于:

  • 静态代码规范检查
  • 开源依赖扫描
  • 单元测试覆盖率
  • 单元测试通过率
  • 动态编译测试
  • 必要的运行测试
  • 文档规范测试

这块可以参照 OpenHarmony 在 Gitee 上的做法:

输入图片说明

这中间最重要的是定义自己所需要的门禁,一般情况下是结合现有工具,将其工作自动化,对于如何跟 Gitee PR 进行联动,可以参照我之前写的一篇文章《基于 Gitee + Jenkins 的开源项目自动化协作实战》

Gitee 近期也在推进 PR Checks、PR Pipeline 等功能,不久将会正式推出,各位可以关注 Gitee 的公众号获取最新进展。

评审改进

在所有的自动化测试以及验证门禁通过之后,我们就需要人工介入进行审查了,因为对于代码来说,自动化脚本甚至智能分析系统给我们的只是既定的规则,对于一些逻辑上的审查,还是需要人工推进的,这里主要是两点工作:

  1. 评审人的指派
  2. 具体评审内容的迭代改进

先来说第一点,关于评审人的指派,有三种做法:

  • 项目的管理员根据所属模块,指定对应比较熟悉的人作为审核者
  • 根据 CODEOWNERS 文件自动进行指派
  • 智能推荐

大部分情况下我们都是结合人工和文件进行半自动的指派的,这种做法是非常常见的,而且也能够结合我们前面说的兴趣小组来对应的进行。

智能推荐是一个比较新的领域,通过新技术来驱动现有技术场景的研发效能改进,说白了就是通过 AI 智能分析代码上下文,包括代码的历史、代码之前的评审过程、文件评论甚至标注等,智能化的推荐相关的审核人,进一步减少指派工作的消耗,并且更加精确的挖掘出相关的评审人员,感兴趣的可以了解下国外的这个产品:https://unreview.io/

第二点就是人工的进行代码的评审,通过评审人对产品以及代码的理解,来维护整个代码结构的发展方向,并且与贡献者进行协商,共同对将要提交到代码库的代码进行优化和改进。

这方面主要是利用平台所提供的功能,通过平台的功能快速的改进及相应,比如 Gitee 的 PR 评论评审功能:

输入图片说明

在所有的信息对齐并且代码也符合整体代码架构预期的时候,代码就可以合入了,但是代码的合入并不是最后的工作,合入后的一些工作也是非常必要的,比如自动生成一些文档、自动生成 CHANGELOG、自动生成制品包等等,这里不再赘述,根据不同项目需要进行配置即可。

共创共建

一个好的开源项目是一群人共同维护、共同发展的,除了常规的代码协作共享工作之外,我们需要能够加入一些运营能力,来推动开源项目的社区健康稳定的发展,所以这里额外加一章,简单聊聊自己的看法。

激励措施

作为一个开源项目,我们需要给贡献者足够的参与感,所以必要的激励措施也是少不了的。

所谓激励,不一定要是说金钱的奖励(当然,有自然是更好的),我们可以通过非常多的渠道进行,来逐步提升开源项目贡献者的参与感:

  • CONTRIBUTORS 文件,标注贡献者名称、头像
  • 社区项目勋章,在开源社区给贡献者发放独有的勋章
  • 贡献者证书,虚拟证书,不仅可以提升参与感,也可以达到传播的效果
  • 实物奖励,T恤、杯子等,只要贡献了代码,就是贡献者
  • 奖杯、实体证书等

输入图片说明

奖励的措施千千万万,但这一切的核心都是以贡献者中心,他们是社区强有力的推动者和参与者,只有项目社区和贡献者形成一个良好的氛围,开源项目社区的发展才能够积极健康的推进发展。

社区运营

运营是一个比较大的话题了,但是一个开源项目是离不开社区支持的,这里所谓的社区是围绕着开源项目的一个圈子。一个开源项目如何扩大自己影响力,如何扩大圈子来获取更多的关注,也是一个非常重要的点。

一般来说一个开源项目发展到一定阶段后,或有专门的运营团队进行跟进,采取了非常多的手段进行推广:

  • 申请大型社区支持(比如成为 Gitee 推荐项目、GVP项目等
  • 举办直播,剖析某一领域的解决方案
  • 举办沙龙,开办用户见面会
  • 参与各种大会,宣讲项目
  • 举办开发者大赛,扩展项目应用案例

输入图片说明

比如近期 OpenHarmony 在 Gitee 上举办了 OpenHarmony 组件开发者大赛,旨在扩大 OpenHarmony 组件应用生态,目前正在报名中,奖项丰厚,感兴趣的可以关注:https://gitee.com/openharmony-2021/

总结

说起开源项目的协作与企业内部研发协作最大的不同点,应该就是管控的范围和力度了。在企业内部,我们可以通过各种各样的制度,来约束开发者的行为,进而建立一个规范化的内部项目生态。

而开源项目的协作就不一样了,贡献者来自全球世界各地,每个人也都有自己不同的个性和想法,所以我们需要更多的投入在规范上,形成统一的认知和约束,并且在工具上落地体现,减少成本。这里其实就跟 DevOps 所推崇的一些理念一样,比如测试左移、日常改进制度化、及时发现问题、群策群力等等。

输入图片说明

我们也需要在开源项目的运营过程中,重视协作并优化工具,把一些可以自动化的工作尽可能的左移,比如把静态测试下放到开发者在本地提交之前,尽早的发现问题并解决,到了提交 PR 之后才检测,问题已经被放大了,修复和处理的成本也会随着时间越来越高,PR 的门禁检测是最后一道门槛,其目的是为了最终确认而不是检测。

甚至我们在资源允许的情况下,可以开放接口,提供远程检测工具链,这样开发者就不必提交一个 Draft PR 来进行这些检测了,直接本地就可以检测并得到结果,或者直接提供一个基于 WebIDE 的调试环境,提前把所有的工作准备好,这样开发者就只需要专注于代码就好。

作为平台方,Gitee 也在持续的进行开源项目的生态工具支撑,比如 Gitee 指数、自定义百度统计、PR 评审等等,近期也在进行 PR 门禁、流水线、评审等功能的推进,在开源项目的社区工具支持上不遗余力的支持,欢迎大家使用和反馈。

对于开源项目协作相关的流程、工具,你有什么好的实践和建议吗?

输入图片说明

转载请保留出处:微信公众号「Zoker 随笔」(zokersay)

Blog Logo

Zoker


Published

Image

Zoker's Blog

专注、沉淀、提升

Back to Overview