16/C4

16/C4

集体代码构建契约 (C4)

集体代码构建契约 (C4) 是 github.com Fork + Pull Model 的演进,旨在为自由软件项目提供最佳协作模型。C4 源自 ZeroMQ 在 2012 年初的贡献政策。

注意: 本 RFC 已被 rfc.zeromq.org/spec:22/C4.1 取代。

语言

本文档中的关键词 “MUST”、“MUST NOT”、“REQUIRED”、“SHALL”、“SHALL NOT”、“SHOULD”、“SHOULD NOT”、“RECOMMENDED”、“MAY” 和 “OPTIONAL” 应按 RFC 2119 中的描述进行解释 (参见“ Key words for use in RFCs to Indicate Requirement Levels ")。

目标

C4 旨在为开源软件项目提供可复用的最佳协作模型。它具有以下特定目标

  • 通过减少新贡献者(Contributor)的阻力并创建一个具有强大正向反馈的规模化参与模型,最大化项目社区的规模;

  • 通过分离不同的技能组合,从而在任何所需领域拥有更大的能力储备,减轻对关键个人的依赖;

  • 通过增加决策过程的多样性,使项目发展更快、更准确;

  • 通过允许安全实验、快速失败和稳定代码的隔离,支持项目版本从实验性到稳定的自然生命周期;

  • 减少项目仓库(repository)的内部复杂性,从而使贡献者更容易参与并减少出错范围;

  • 强制执行项目的集体所有权,这增加了对贡献者的经济激励,并降低了被恶意实体劫持的风险。

设计

前提

  • 项目 SHALL 使用 git 分布式版本控制系统。

  • 项目 SHALL 托管在 github.com 或同等平台上,在此统称为“平台”。

  • 项目 SHALL 使用平台的问题追踪器(issue tracker)。

  • 项目 SHOULD 有清晰记录的代码风格指南。

  • “贡献者”(Contributor)是指希望提供补丁(patch)的人,补丁是一组提交(commit),用于解决某个明确识别的问题。

  • “维护者”(Maintainer)是指将补丁合并到项目中的人。维护者不是开发者;他们的职责是执行流程。

  • 贡献者 SHALL NOT 拥有对仓库的提交权限,除非他们同时也是维护者。

  • 维护者 SHALL 拥有对仓库的提交权限。

  • 任何人,无论区别或歧视,SHALL 根据本契约的条款拥有成为贡献者的平等权利。

许可与所有权

  • 项目 SHALL 使用 GPLv3 或其变体(LGPL, AGPL)。

  • 所有对项目源代码的贡献(“补丁”)SHALL 使用与项目相同的许可。

  • 所有补丁归其作者所有。SHALL NOT 有任何版权转让流程。

  • 项目 SHALL 由其所有贡献者集体所有。

  • 每位贡献者 SHALL 负责在项目贡献者列表中表明身份。

补丁要求

  • 维护者和贡献者 MUST 拥有一个平台账户,并且 SHOULD 使用他们的真实姓名或一个广为人知的别名。

  • 一个补丁 SHOULD 是对一个明确识别和同意的问题的最小且准确的解答。

  • 如果项目定义了代码风格指南,补丁 MUST 遵守这些指南。

  • 补丁 MUST 遵守下文定义的“公共契约的演进”指南。

  • 补丁 SHALL NOT 包含来自其他项目的非平凡(non-trivial)代码,除非贡献者是该代码的原始作者。

  • 补丁 MUST 在至少最重要的目标平台上能干净地编译通过。

  • “正确补丁”(Correct Patch)是指满足上述要求的补丁。

开发流程

  • 项目的变更 SHALL 由准确识别问题并对这些问题应用最小、准确解决方案的模式来管理。

  • 要发起变更,用户 SHALL 在项目平台的 issue tracker 上记录一个问题(issue)。

  • 用户 SHOULD 通过描述他们面临或观察到的问题来撰写 issue。

  • 用户 SHOULD 寻求对其观察准确性和解决问题价值的共识。

  • 用户 SHALL NOT 记录功能请求、想法、建议或任何未明确记录和可证明的问题的解决方案。

  • 因此,项目的发布历史 SHALL 是一系列已记录和已解决的有意义的 issue。

  • 要处理一个 issue,贡献者 SHALL fork(派生/创建分支)项目仓库,然后在他们 fork 的仓库上工作。

  • 要提交补丁,贡献者 SHALL 创建一个平台 pull request(合并请求/拉取请求)到项目中。

  • 贡献者 SHALL NOT 直接提交变更到项目中。

  • 要讨论补丁,人们 MAY 在平台 pull request、提交或其它地方发表评论。

  • 要接受或拒绝补丁,维护者 SHALL 使用平台接口。

  • 维护者 SHALL NOT 接受自己的补丁。

  • 维护者 SHALL NOT 对正确补丁进行价值判断。

  • 维护者 SHALL 快速合并正确补丁。

  • 贡献者在为 issue 创建 pull request 后,MAY 将 issue 标记为“Ready”(准备就绪)。

  • 创建 issue 的用户在检查补丁成功后 SHOULD 关闭该 issue。

  • 维护者 SHOULD 要求改进不正确的补丁,并且如果贡献者未能建设性地回应,SHOULD 拒绝不正确的补丁。

  • 对正确补丁有价值判断的任何贡献者 SHOULD 通过他们自己的补丁来表达这些判断。

  • 维护者 MAY 直接提交非源代码文档的变更到项目中。

创建稳定版本

  • 项目 SHALL 有一个分支(“master”),该分支始终包含最新的进行中版本,并且 SHOULD 始终能够构建。

  • 项目 SHALL NOT 使用 topic branches(主题分支)出于任何原因。个人 fork MAY 使用 topic branches。

  • 要创建稳定版本,某人 SHALL 通过复制仓库来 fork 它,从而成为该仓库的维护者。

  • 为稳定化而 fork 项目 MAY 单方面进行,无需项目维护者的同意。

  • 稳定化项目的维护者 SHALL 通过 pull request 来维护它,这些 pull request MAY cherry-pick(挑选)来自被 fork 项目的补丁。

  • 对声明为“stable”(稳定)的仓库的补丁 SHALL 附带可复现的测试用例。

  • 稳定化仓库 SHOULD 经历以下阶段:“unstable”(不稳定)、“candidate”(候选)、“stable”(稳定),然后是“legacy”(遗留)。也就是说,稳定化仓库的默认行为是“死亡”。

公共契约的演进

  • 所有公共契约(API 或协议)SHOULD 有文档记录。

  • 所有公共契约 SHALL 使用语义版本控制(Semantic Versioning)(参见“ Semantic Versioning 2.0.0-rc.1 ")。

  • 所有公共契约 SHOULD 有可扩展性和实验的空间。

  • 修改公共契约的补丁 SHOULD 不破坏现有应用程序,除非事先就这样做的好处达成共识。

  • 为公共契约引入新功能的补丁 SHOULD 使用新名称。

  • 旧名称 SHOULD 以系统化的方式被弃用:将新名称标记为“experimental”(实验性)直到其稳定,然后将旧名称标记为“deprecated”(已弃用)。

  • 当足够时间过去后,旧的已弃用名称 SHOULD 被标记为“legacy”(遗留),并最终移除。

  • 旧名称 SHALL NOT 被新功能重用。

  • 当旧名称被移除时,如果应用程序使用它们,其实现 MUST 引起异常(断言)。