这篇文档基于 ASF 官方的发版指南做提取和精简, 关注我们在发版过程中最容易忽视/犯错的部分, 初次参与发版的同学, 尤其是每个仓库/模块的负责人都需要完整, 仔细的通读一遍, 不确定的地方请及时沟通询问。
注: 本文主要以已加入 incubator, 也就是正在孵化中的项目为背景进行描述, 不再对已毕业项目和其他类型做额外解释说明。
*发版指南:
https://infra.apache.org/release-distribution.html
0. 前言
相信对于每个初入 ASF 的孵化项目来说,第一次发版都会遇到不少小问题和麻烦事,尤其以 License/Notice/Copyright 相关的问题为典型代表,思考了下主要原因可能有:
-
ASF 官方的文档颇为零散,社区的普通开发者和未参与发版的同学经常没有耐心通读所有文档以及注意到关键事项 (或理解有偏差); -
ASF 官方文档对于有些描述仍较为模糊, 或者它直接建议 PMC/Mentor/Mail 来讨论决策,但这部分结论通常没有更新记录到文档中; -
ASF 官方没有给大家推荐类似 skywalking-eye (header/dependency) 的自动化检查工具,这些工具对初次发版的同学可能会有许多帮助; -
ASF 文档中对有些规范/规则并未严格要求, 但发版投票时不同的 Reviewer 可能有不同的习惯/偏好, 从而会提出一些改进”建议”; -
“中/英"语言/语义上的理解偏差,从而导致了某些内容的误解。
*Apache HugeGraph: https://github.com/apache/incubator-hugegraph
0.1 名词
-
ASF: Apache Software Foundation -
ASL2.0: Apache Software License 2.0
-
每个源码 & 二进制包(包括发行的 jar 包)都必须提供 LICENSE + NOTICE + DISCLAIM ER 文件: -
源码(source)包必须位于项目根目录下; -
二进制包一般也在根目录下 (注: 此项参考其他 ASF 项目, 目前没发现 ASF 有硬性要求)。 -
LICENSE 文件原始版本必须格式/内容完整正确,请直接下载官方提供版本然后放在项目目录中 (避免手动复制粘贴文本)。 -
建议 LICENSE/NOTICE 文件不要包含不必要的信息,比如不要包含你没有使用到的依赖的 LICENSE,如果移除/更新了依赖,则需要及时更新/移除对应的 LICENSE/NOTICE 信息。 引用的第三方 license ,必须将详细信息附加到我们的 LICENSE 文件后, 如果引用的 LICENSE 很长,则需要单独存储一个文件并指向它们, 如 LICENSE-<dependency-name>.txt 。 -
如果是引用代码方是标准的(未经修改)的 APL2.0 协议,则可以说明对方是标准版本,直接参考根目录下的 APL2.0 LICENSE, 无需重复拷贝。 -
二进制包还需要特别注意,通常它携带的 LICENSE + NOTICE 文件内容和源码包有许多区别,请勿直接复用同一文件: -
源码包通常不携带二进制/jar 包/图片等依赖,所以它的 LICENSE 和 NOTICE 会简单干净得多,它主要是对源码引用做声明。 -
二进制包一般是在源码包的两个文件引用基础上,还需补充所有引用的第三方依赖/图片/二进制等文件及其对应指向的 LICENSE 文件。 -
一个第三方依赖如果有多个 LICENSE 许可(例如 ASL2.0 & GPL ),建议仅选择一个 LICENSE 引用,而不是列出所有 (不方便他人 review): -
一般多选一的基本依据是选择 ASF 文档中提到的 A 类宽松许可 ,如没有再考虑 B 类等; -
如果这个依赖的 LICENSE 文件是独立存在的,也应该只选取其中所选的内容 (例如去掉其中 GPL 或其他多余的声明引用); -
的确可见有 ASF 项目在 LICENSE 文件中引入了依赖所有 LICENSE 条目,但可能并非提倡的写法(应避免参考照搬)。
*官方说明: https://infra.apache.org/licensing-howto.html
* LICENSE 文件官方版本: https://www.apache.org/licenses/LICENSE-2.0.txt
* A 类宽松许可: https://www.apache.org/legal/resolved.html#category-a
-
httpd - source -
https://svn.apache.org/repos/asf/httpd/httpd/trunk/LICENSE -
seatunnel - source -
https://github.com/apache/incubator-seatunnel/blob/dev/LICENSE -
seatunnel - binary -
https://github.com/apache/incubator-seatunnel/blob/dev/seatunnel-dist/release-docs/LICENSE -
linkis - source -
https://github.com/apache/linkis/blob/master/LICENSE -
linkis - binary -
https://github.com/apache/linkis/blob/master/linkis-dist/release-docs/LICENSE
-
首先,大部分开源组织都要求项目的每个源文件都有一个明显的 License 声明,这样当他人单独引用某个文件时才最容易保留声明/也最直观清晰; -
其次,考虑到原始的 LICENSE 文件一般很长,为了简洁起见它就规定在文件头部引用一个简略版本,简称 license header, 然后完整版本放在根下 (LICESEN文件) ,形成一个引用关系; -
所以可以看到哪怕同为 ASL2.0协议, 不同项目的 license header 可能并不完全相同,有增/减部分内容都是正常的 (请勿自行"统一”)。
*原始的 LICENSE: https://www.apache.org/licenses/LICENSE-2.0.txt
-
ASF 规定名下项目 license header (文件头)中不能包含 Copyright 声明, 这部分应该考虑: -
若不必要,例如捐赠之前的 Copyright 自愿舍弃, 那直接移除即可; -
若需要,则在 NOTICE 文件头部单独声明。 -
特别注意,如果是引用了第三方的代码,切勿删除/修改对方 header 及其包含的 Copyright 声明,更不要添加额外的 ASL2.0 头: -
大家一般习惯通过插件/脚本进行批量格式化,此时要单独检查第三方代码没有添加额外的 ASL2.0 声明; -
另一个常见的问题就是只引用了部分代码, 此时应如何处理呢? -
小修改/增加(对第三方代码) ,一般应使用原文件的 license, 不修改原本的 license/author 内容; -
大修改 ,ASF 建议是 PMC 具体讨论处理 (这里没有严格定义"大/小"修改的区分方式, 所以如无必要就视作小修改处理吧); -
如果是在一个(上千行)大文件中引用了一个内部结构体/类 (几十行) , 此时该如何保留它的 license 头引用呢? (应尽量避免, 详见文尾单独讨论) -
哪怕第三方代码的 header 格式/语法/标点等有问题,或者不完整(精简版),也请勿修改原始的 License Header 。 -
同前文, 如果一个软件/代码整体包含多个可选许可, 请考虑以下二选一: -
优先选择 Apache 最适配的 A 类宽松许可作为 license header ,避免不必要麻烦; -
如果原代码 license header 中已经同时提到了多种可选许可, 则不用修改 (因通常原代码作者才有权修改)。
*A类宽松许可: https://www.apache.org/legal/resolved.html#category-a
-
简短的文本信息 (典型 READEME, CONTRIBUTING, *.txt, *.md, *.log 以及各种 lint 文件); -
增加了头注释可能会报错的文件 (典型 json 文件); -
源码打包时可排除的文件, 例如 .github 下的专用 action 文件, .git 或类似文件。
-
包管理/依赖配置文件,例如 Makefile/pom.xml 等,ASF 建议如无必要, 都加一下免得引入纠纷 (参考邮件讨论); -
程序生成的模板/用户使用的 *.conf, *.properties 文件可视具体情况 PMC 讨论,不确定的或单元测试中使用的配置文件建议建议默认都带上 (或向上咨询); -
如果存在压缩的 css/js 等文件,如果是自己项目开发产生的,则建议使用简短版本的声明,而不建议使用原始的 header 版本。
*部分不需要添加 license header 的文件: https://www.apache.org/legal/src-headers.html#faq-exceptions
*包管理/依赖配置文件是否添加 license header 的邮件讨论: https://lists.apache.org/thread/l6w0ytfodywfsb6ky0gd41qfzb148r50
*自己项目开发产生的存在压缩的 css/js 等文件的简短版本声明: https://www.apache.org/legal/src-headers.html#is-a-short-form-of-the-source-header-available
-
NOTICE 文件必须遵循 ASF 的标准规范, 不可随意修改格式 (建议参考已发版过的 incubating 项目,已毕业项目可能有历史原因请勿直接照搬); -
NOTICE 文件的 Copyright 年份尽量保持统一(例如有多个repo),并且最终年份应该随发版时进行更新 (例如 2017-20xx, 发版应检查 xx 年份); -
如果我们引用了其他 ASF 的项目,参考此处 (https://infra.apache.org/licensing-howto.html#bundle-asf-product,注意这和引用了普通 Apache2.0 协议的项目不是等同的); -
尽可能保持 NOTICE 简洁,不确定的引用请咨询社群/导师,这里不应先假定需要,因为它会给使用方(下游)带来额外负担 (传递性); -
BSD/MIT 许可证内嵌的 Copyright 通知不需要重新引用 (LEGAL-59); -
如果第三方依赖的 NOTICE 文件错误的引用了 LICENSE 或者其他信息,我们该如何选择? -
一般情况不用照搬错误部分, 只需要选取需要/合规的部分即可 (refer issue:https://github.com/apache/incubator-hugegraph-computer/pull/227#discussion_r1081107569); -
不能确定的可以咨询导师/邮件 incubator 社区。
*LEGAL-59: https://issues.apache.org/jira/browse/LEGAL-59
-
官方最简模板 (推荐) -
https://www.apache.org/licenses/NOTICE-2.0.txt -
seatunnel (推荐) -
https://github.com/apache/incubator-seatunnel/blob/dev/NOTICE -
HTTP Server (不太推荐) -
https://www.apache.org/licenses/example-NOTICE.txt
-
标准版: 可以遵循 ASF 的所有发布政策的孵化项目,命名为 DISCLAIMER 文件 (条件允许应优先考虑); -
WIP (Work In Progress) 版本: 意味着发版过程中会有部分不能满足 ASF 要求的发布政策,命名为 DISCLAIMER-WIP, 这里”不满足“的条件较为宽松,例如 *GPL/CC-BY 等 X 类不兼容的许可都可以容忍 (若更特殊的情况最好是咨询导师/邮件)。
*官方说明: https://incubator.apache.org/policy/incubation.html#disclaimers
-
将这种 ASF 不允许携带的引用变为可选项,例如 oracle 的 ojdbc.jar 包, 可以写文档告诉需要的用户去自行下载然后关联/启用上; -
若一个项目协议允许多种许可,只要包含和 ASL2.0 兼容的许可即可使用,并且在项目 LICENSE文件中指定我们选择的许可; -
另外要注意 CC (Creative Commons) 许可,若单独出现 ASF 也是不允许(https://www.apache.org/legal/resolved.html#cc-by)的 (这个可能大家容易忽视, 建议使用插件扫描)。
*ASF官方禁止引用第三方开源许可协议软件列表: https://www.apache.org/legal/resolved.html#category-x
-
二进制文件在源码包中尽量不要出现,如果已存在的考虑通过编译/测试时通过下载 or 临时生成代替 (新 PR 应避免重新引入); -
比较巨大/难以 review 的压缩文件 (例如 swagger-ui 虽是 Apache 许可的前端包),也尽量不要直接引入到源码,而应在编译时下载解压代替。 -
大部分图片也会被视为二进制文件,这部分如非源码必要,可考虑打包时排除。 -
如果是必要的图片/二进制,则需要在 LICENSE 文件中有单独的引用说明 (待补充好的示例)。
-
发版分支可以进行单独更新,但是一旦发版 VOTE 邮件发出,则必须固化下来/停止后续任何更新提交 (否则会被视为不合规); -
发版的时候,因为很可能有多轮,所以建议 tag 使用 rc 后缀,例如 1.0.0-rc1 代表第一次投票,打回则递增 rc 数字 (非强制但建议); -
分支 (branch) 按 ASF 邮件(https://lists.apache.org/thread/k08vq5r4nfos2ptn69w2fbm2mvmkb91n)中提到并不需要,所以保留 release-1.0.0 复用即可; -
可以在发版邮件里携带 tag 最近一次的 Commit-ID (缩略位即可),方便确认; -
发版未完成之前,官网的下载页面不可携带临时下载地址 (同理 Github 的 Release 页面务必使用 pre- release 而不可使用 latest release; -
官网下载页面或项目的 README 中最好有基本的 “完整性校验” + “如何编译源码” 的文档说明 (非必要但建议)。
-
maven RAT check 二进制/header/archives (maven 插件, 仅适用 Java 系 - 必要); -
skywalking-license-header check (还可提供 PR 内 comment 提醒, 很棒 - 必要); -
skywalking-dependencies generation & check (建议至少开启 check 部分, 文档同上 - 可选); -
validate release package (可参考 HugeGraph 编写的自动验证 action, 提前检查 GPG/SHA/二进制文件/空文件 (夹)等 - 推荐); -
dependency-review-action (GitHub 官方提供可检查/排除 license 的 Action - 可选)。
*skywalking-license-header check: https://github.com/apache/skywalking-eyes
*HugeGraph 编写的自动验证 action: https://github.com/apache/incubator-hugegraph-doc/blob/master/.github/workflows/validate-release.yml
*dependency-review-action: https://github.com/actions/dependency-review-action
-
如果引用第三方的代码(源码)后,需要同时在 source & binary release 的不同 LICENSE 文件中都添加引用么? A: 是的, 都需要 (refer issue)。 -
关于 license header 的几个点: -
(原则)不建议大家片段化使用第三方代码,应优先考虑分离开 or 自己重写,不得已引用的时候需要保留原有代码的 license header; -
(原则)将第三方代码从一种编程语言转换成另一种编程语言,不属于重大修改,需保留原 license header (在一些算法相关的代码中较常见); -
(特殊情况) 如果引入的第三方代码只是某个代码文件中的一小部分, 是否应该用它的 license header 作为整个文件的头? -
如果引入的是一个接口定义/子类/结构体,可否直接在这部分代码片段上引入它的 license header; -
如果不能在代码中间位置引入 license header, 那么头部是否允许保留两个license header (一个是 ASF 的, 一个是引入的); -
如仅保留一个 license header, 是否需要在 LICENSE 文件中说明引入的代码行范围,不引入的话似乎他人不知道哪部分代码是 refer 的;
转载自丨ALC Beijing
作者丨imbajin
编辑丨罗蕊艳
相关阅读 | Related Reading
开源社顾问委员会2023年第一季度会议圆满举办!
类 ChatGPT 开源软件,开发者用的上吗?

本文分享自微信公众号 - 开源社KAIYUANSHE(kaiyuanshe)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。