JEP 369:迁移到 GitHub
总结
在 GitHub 上托管 OpenJDK 社区的 Git 仓库。结合 JEP 357(从 Mercurial 迁移到 Git),这将会把所有单一仓库的 OpenJDK 项目迁移到 GitHub,包括 JDK 特性发布 和版本 11 及之后的 JDK 更新发布。
目标
- 在 https://github.com/openjdk/ 上托管所有 OpenJDK Git 仓库。
- 在每次推送之前运行预提交检查(jcheck)。
- 集成现有的 OpenJDK 服务。
- 启用与 GitHub 交互的多种方式。
- 确保支持在结构上类似于现有电子邮件和 webrev 工作流的工作流。
- 保留并归档所有元数据。
- 确保 OpenJDK 社区始终可以迁移到其他源代码托管提供商。
- 不要求开发者安装 OpenJDK 特定工具即可贡献代码。
- 不更改 OpenJDK 章程。
- 不更改 OpenJDK 人口普查。
非目标
成功指标
- 显著更快的克隆和拉取时间
- 更好的仓库可用性(正常运行时间)
- 可以通过 OpenJDK 邮件列表与 GitHub 上的仓库进行交互
- 可以通过命令行工具与 GitHub 上的仓库进行交互
- 可以通过网页浏览器与 GitHub 上的仓库进行交互
动机
此 JEP 的动机分为两部分。首先,我们讨论为什么使用外部源代码托管服务提供商将使 OpenJDK 社区受益,然后我们解释为什么 GitHub 是目前最佳的服务提供商选择。
为什么选择外部源代码托管提供商?
外部源代码托管提供商是指并非由 OpenJDK 社区中的贡献者实施和管理的源代码存储库服务。外部提供商的示例包括 BitBucket、GitLab、Phacility、SourceForge 和 GitHub。
OpenJDK 社区使用外部源代码托管服务提供商主要有三个原因:
-
性能。许多(如果不是全部的话)提供商都有出色的性能,不仅在网络性能方面,在可用性(即正常运行时间)方面也是如此。对于 OpenJDK 社区来说,这将显著加快克隆和拉取的时间,并且源代码仓库的可用性会更高。
-
API。将 OpenJDK 仓库托管在源代码托管平台上的一个技术原因是获得访问 Web API 的权限,这些 API 能让程序与平台上的开发者进行交互。尽管目前通过电子邮件与开发者互动也能实现这一目标,但开发能够解析电子邮件中自由格式文本的程序要困难得多,而使用结构化的 API 则相对容易。允许程序参与评审过程可以实现强大的自动化;有关几个示例,请参见描述部分。
-
扩展社区。最大的提供商还将为 OpenJDK 社区提供机会,接触大量现有的开发者和潜在贡献者。如果开发者已经在某个提供商上拥有账户,则只需很少的额外步骤即可为 OpenJDK 做出贡献。较大的 Java 社区中的几乎所有开源项目都托管在外部提供商上,其中包括多个 OpenJDK 发行版。如果 OpenJDK 仓库也托管在同一提供商上,这将促进更紧密的合作。
使用外部供应商的一个缺点和风险是,供应商可能会关闭,或者由于其他原因导致源代码和相关资料无法访问。有关如何处理和缓解此风险的信息,请参见风险与假设部分。
另一个需要考虑的因素是,转移到外部供应商会对现有贡献者的工作流程产生什么影响。请参阅 Description 部分,了解如何在源代码托管平台的 API 帮助下支持多种工作流程,包括如何保留几乎所有的 OpenJDK 社区现有工作流程。
为什么选择 GitHub?
选择 GitHub 的动机在于,它在选择外部提供商的三个主要原因上都表现出色。GitHub 的性能与其他提供商一样好或更优,它是全球最大的源代码托管服务(截至 2020 年 5 月已有 5000 万用户),并且拥有最广泛的 API 之一。
GitHub 广泛的 API 使得许多工具(包括文本编辑器、IDE、命令行工具和图形桌面客户端)都能够支持 GitHub。以下文本编辑器支持 GitHub(即,开发者可以直接在文本编辑器中创建、审查和评论拉取请求):
以下集成开发环境(IDE)支持与 GitHub 上的拉取请求进行交互:
还有命令行形式的客户端,例如 hub(开源),以及多个图形化的桌面客户端,例如 SourceTree、Tower 和 GitHub Desktop(开源)。
还有许多其他优秀的源代码托管服务提供商。有关这为何重要以及这如何使我们能够推荐 GitHub,请参见风险与假设部分。
描述
迁移到外部源代码托管服务提供商的有趣之处 并不在于 将实际的代码仓库上传到该服务;鉴于 JEP 357(从 Mercurial 迁移到 Git) 中的工作,这一步非常简单。
真正有趣的是,迁移到外部提供商将如何影响 OpenJDK 贡献者的工作流程。
如今,OpenJDK 的贡献者通过邮件列表进行协作,他们将更改推送到Mercurial 仓库,通过jdk/submit服务测试更改,并通过JDK Bug 系统(JBS)提交错误报告。贡献者还可以使用多个命令行界面(CLI)工具,主要是jcheck、webrev和defpath。这是一种让许多有经验的贡献者感到愉悦且高效的工作流程。因此,如果我们转向外部提供商,保留尽可能多的这种工作流程是至关重要的。
GitHub 和其他流行托管平台上的工作流程采用了 拉取请求(PR)的概念,从高层次上看,这与 OpenJDK 贡献者目前使用的请求审查(RFR)电子邮件类似。GitHub 上的贡献者会从一个源分支向特定仓库中的目标分支创建一个 PR(源分支和目标分支不必位于同一个仓库中)。然后,其他贡献者会对该 PR 进行审查,并根据评审反馈对源分支进行额外的提交。一旦评审者对更改感到满意,PR 就会被合并到目标分支中。
此 JEP 提议支持多种工作流,使用在 Project Skara 中开发的工具。贡献者可以选择最适合他们的任何工作流:
- 基于 CLI 和邮件列表(类似于当前的工作流程)
- 基于 Web 浏览器(通过 GitHub 网站)
- 基于文本编辑器和 IDE(通过插件以及文本编辑器和 IDE 中的 GitHub 支持)
- 基于 CLI(通过自定义 CLI 工具)
当然,可以混合和匹配不同的工作流程。在一个像 OpenJDK 这样庞大且多样化的开源社区中,各个贡献者的工作流程唯一的共同点就是它们各不相同。在描述各种工具和服务之前,我们先从一个引入新变更的工作流程示例开始。(有关更专门任务的工作流程,例如在存储库之间同步或添加标签,将在本 JEP 的未来修订版中讨论。)
工作流程
创建 PR 后,PR 中的提交会由 jcheck 提交分析工具进行分析,该工具作为服务器端程序运行(所谓的“机器人”)。jcheck 机器人使用外部提供商的 API 根据提供商 API 的功能将潜在问题以评论或错误的形式展示出来。在 GitHub 上,jcheck 机器人特别利用 Checks API 来生成信息丰富的错误消息。jcheck 机器人可以通过仓库中的 .jcheck/config
配置文件进行配置。如果已配置,其中一项检查会确保所提议的更改在 JBS 中有相应的问题。在这种情况下,机器人会确保 PR 的标题与 JBS 问题的标题相对应,类似于 RFR 电子邮件的标题。如果 PR 的标题包含一个 JBS 问题,那么 jbs 机器人会在相应的 JBS 问题中添加一个指向该 PR 的 链接。
一旦 PR 通过了 jcheck,它就会获得 "rfr"
标签。这向潜在的审查者表明,该 PR 现在已经准备好进行审查。(审查者参与一个甚至无法通过 jcheck 的更改是没有意义的。)此时,PR 还会根据 PR 中提交所更改的源代码区域自动添加标签。例如,一个针对 jdk 仓库 master
分支的 PR,如果同时更改了 make
目录和 src/hotspot
目录,则会获得 build-dev
和 hotspot-dev
标签。一封自动生成的 RFR 邮件会被发送到邮件列表 build-dev@openjdk.java.net
和 hotspot-dev@openjdk.java.net
,以及 PR 作者指定的任何其他邮件列表。RFR 邮件包含 PR 的标题和正文、PR 中提交的自动生成的摘要,以及指向自动生成的 webrevs 的链接。
评审人员现在可以使用多种工作流程来讨论 PR 中的变更:
- 通过回复发送到邮件列表的 RFR 电子邮件,回复内容会被复制到 GitHub 上的 PR 中(不需要 GitHub 帐户);
- 通过 Web 浏览器使用 https://github.com/ 上的审查工具;
- 通过使用与 GitHub 集成的各种文本编辑器和 IDE 中的审查工具;
- 通过使用与 GitHub 集成的图形桌面应用程序;或者
- 通过使用 Skara CLI 工具。
在任何工作流程中发表的评论都会反映在所有工作流程中。一位评审员可以通过邮件列表添加评论,另一位通过网页浏览器,第三位通过命令行,他们都将看到彼此的评论。
如果 PR 作者根据评审人员的反馈向源分支推送了额外的提交,那么一个机器人会回复 RFR 邮件,包含新提交的自动摘要以及自动生成的增量和完整 webrev。
由于评审者对更改感到满意,他们会将 PR 标记为已评审。可以采用以下方法进行:
- 使用网页浏览器和 https://github.com/,
- 使用命令行中的
git pr approve
, - 使用带有 GitHub 集成的文本编辑器和/或 IDE,或者
- 使用带有 GitHub 集成的图形桌面工具。
一旦所有审查者都满意了,PR 的作者就可以最终整合该 PR。他们通过添加内容完全为 /integrate
的评论来实现这一操作,之后会发生一系列的事情:
- 一个机器人将所有提交压缩(合并)为一个提交。
- 如果有必要,一个机器人会在目标分支(通常是
master
)之上对压缩后的提交进行变基。 - 一个机器人会为最终的提交构建提交信息,其中包括:
- 将 PR 的标题作为提交信息的标题,
- 基于 PR 中以
/summary
开头的评论生成正文, - 在
Reviewed-by:
尾部添加所有评审人的 OpenJDK 用户名,以及 - 在
Co-authored-by:
尾部添加所有合作者。
- 一个机器人将生成的提交推送到目标分支(通常是
master
)。
作者可以在实际整合 PR 之前预览发出 /integrate
命令的结果,包括提交信息。
权限和角色
工具
Skara 项目的贡献者开发了各种支持此 JEP 的工具,包括在贡献者计算机上本地运行的 CLI 工具和在提供商服务器上运行的服务器端工具(“机器人”)。CLI 工具主要用于帮助希望通过命令行与外部提供商交互的贡献者。这些工具包括:
git-fork
:在外部提供商上 fork 一个项目并克隆它git-pr
:更新、批准、获取、显示等操作一个拉取请求git-sync
:从上游仓库同步分支git-publish
:将本地分支发布到远程仓库git-info
:从提交信息中提取 OpenJDK 特定的信息git-token
:与 Git 凭证管理器交互以处理令牌git-proxy
:通过 HTTP(S) 代理代理所有来自 Git 命令的网络流量git-skara
:学习关于 Skara CLI 工具并进行更新
以下 CLI 工具已经提供,以支持 JEP 357(从 Mercurial 迁移到 Git):
git-jcheck
:在本地运行 jcheckgit-webrev
:创建一个 webrevgit-defpath
:设置推送和拉取路径git-translate
:在 hg 和 git 哈希之间进行转换
协助贡献者的机器人有:
pr
:检查、标记并集成拉取请求ml-bridge
:在邮件列表和源代码托管服务之间桥接评论notify
:推送后向邮件列表发送通知archiver
:以 JSON 格式在 Git 仓库中存档所有 PR 元数据forwarder
:将推送的提交转发到其他仓库(例如,沙盒)jbs
:更新 JBS(类似于现有的 "hgupdater" 服务)submit
:作为机器人实现的测试服务示例
服务
除了这些机器人之外,还有两项服务可帮助贡献者和审核者:
-
OCA 服务减轻了审查人员检查贡献者是否签署了 Oracle Contributor Agreement 的负担。
-
测试服务 是 jdk/submit 仓库的通用版本。它允许贡献者在 PR 评论中发出
/test
请求,一个或多个测试服务可以对此进行响应。一个简单的测试服务示例已经以提交机器人(submit bot)的形式提供。
替代方案
测试
风险与假设
切换到外部源代码托管提供商的主要风险是 OpenJDK 社区可能会对该提供商产生依赖性。由于 Git 的分布式特性,版本控制数据本身将始终独立于提供商。然而,像代码审查评论这样的元数据可能会被锁定在某个特定的提供商中,这是存在风险的。此外,工具和工作流程可能会对某个特定的提供商产生依赖性,从而导致由于工具中的假设而无法更换提供商。
减轻这些风险一直是 Skara 项目的主要关注点。以下设计决策确保关键元数据不会锁定到任何特定的提供商:
-
拉取请求中的所有讨论都会复制到相应的 OpenJDK 邮件列表。
-
拉取请求中的所有讨论都会以两种格式存档:mbox(供人类阅读)和 JSON(供软件使用)。
-
推送通知会发送到相应的
*-changes@openjdk.java.net
邮件列表,从而避免依赖于提供商的 RSS 源。 -
OpenJDK 人口普查 用于用户组织和权限级别,从而避免依赖于提供商的用户组织工具。
-
域名 https://git.openjdk.java.net/ 会重定向到 OpenJDK 社区当前的源代码托管提供商。记录在 JBS 问题 和邮件列表消息中的源代码 URL 使用此域名,而不是当前提供商的域名。
为了防止 Skara 工具依赖于特定供应商的 API,从一开始支持多个外部供应商就是一个严格的要求。所有工具还必须与开源的 GitLab Community Edition(GitLab CE)一起使用。