2021年2月3日,JFrog宣布,他们将关闭Bintray和JCenter。这篇文章告诉你,你需要知道什么,做什么来避免你的构建管道受到干扰。
你的构建可能会受到这种关闭的影响,有几种方式。
- Gradle可能无法下载用于编译、测试或运行你的代码的依赖项。
- Gradle可能无法下载用于配置你的构建的插件的依赖项。
- Gradle可能无法再将你的软件包发布到Bintray。
此外,当从一个软件库转移到另一个软件库时,你应该注意到安全方面的考虑。
更新:JFrog已经决定将JCenter无限期地作为一个只读的软件库。JCenter上不再接受新的软件包和版本。所有Bintray服务都已关闭。
背景介绍
JCenter是一个中央工件库,就像Maven中心一样。软件项目使用JCenter向其他人分发他们的软件。JCenter也是Maven Central的一个镜像,所以Maven Central上的任何依赖项在JCenter上也是可用的(但反之亦然)。
Bintray是一个管理层,软件项目用它来向JCenter发布和推广软件包。Bintray还允许用户创建与JCenter隔离的公共用户专用资源库。
这两个服务都会受到关闭的影响。
对构建的影响
默认情况下,Gradle不会向你的项目添加工件库;然而,Gradle确实提供了一个方便的API来使用JCenter库。
GradleBuild Init插件产生的构建模板会使用JCenter仓库来解决依赖关系。在许多代码示例和文档中,JCenter被用作示例仓库。
你很可能有依赖JCenter的构建。我们在GitHub上发现了超过一百万个使用JCenter与Gradle的Git仓库。
为了阻止新项目使用JCenter,我们将从样本和init模板中删除JCenter。新的默认值将是Maven Central。Gradle本身与JCenter或Maven Central没有内在联系,所以你可以随时切换你选择的任何其他仓库。这一变化将在下一个Gradle版本--Gradle 7.0中生效。
Gradle 7.0还将废除使用jcenter() 来解决依赖关系。你仍然能够使用JCenter作为仓库,但Gradle会发出一个废弃警告。jcenter() 方法将在下一个主要版本中被删除。
2021年3月31日之后,托管在JCenter上的软件包将需要找到一个替代的资源库来提供更新。许多软件包可能会迁移到Maven Central,但有些软件包可能根本不会迁移,有些可能只发布新版本。被遗弃的项目可能会因为其他维护者的接手而改变其坐标。这意味着从JCenter过渡到另一个资源库将比简单地使用不同的资源库URL更困难。
根据目前的时间表,使用JCenter的构建将能够解决依赖关系,直到2022年2月1日而不发生变化。在那个日期之后,如果你继续使用JCenter,就不能保证你能够构建你的软件。
你该怎么做?
按照下面的步骤,为JCenter的关闭准备好你的构建。
- 确定您的构建是否使用 JCenter
- 从你的构建中删除JCenter,用Maven Central取代它。Gradle也为该资源库提供了方便的API。
- 运行你的构建管道,看看一切是否仍然正常。
- 如果你的构建成功了,你就完成了。
- 如果你的构建失败了,你就需要对哪些依赖关系仍然需要JCenter进行排查。
你怎么知道你是否在使用JCenter?
有几种不同的方法可以检查你是否在使用JCenter。
多年来,JCenter一直是Android项目的默认资源库。如果你正在构建一个Android应用程序,你可能正在使用JCenter。
Gradle插件门户目前隐含地反映了JCenter。如果你正在使用Plugin Portal(通过gradlePluginPortal() 或URL plugins.gradle.org/m2)来解决你的应用程序的依赖关系,你可能正在依赖JCenter。你应该避免使用Plugin Portal作为仓库,除非是Gradle插件项目。
请注意,Bintray也允许任何用户用自定义的URL来运行他们自己的公共仓库。这也会受到关闭的影响。你应该检查你是否在使用一个URL以dl.bintray.com开头的版本库。由于这些软件库可以包含任何东西,你需要弄清楚你从这些软件库中使用了哪些依赖项,以及它们可能会迁移到哪里。
检查构建扫描
如果你正在使用Gradle Enterprise或公共构建扫描服务,你可以检查哪个软件库被用来解决你的依赖关系。
这将帮助你确定哪些依赖项最有可能受到关闭的影响。
检查构建文件
如果你在你的构建脚本中声明了你的资源库,你可以寻找jcenter() 或URL jcenter.bintray.com。
你要找的是类似于
repositories {
jcenter()
}
或
repositories {
maven {
url = "https://jcenter.bintray.com"
}
}
或
repositories {
maven {
url = "https://dl.bintray.com/<some user name>"
}
}
检查插件
任何自定义的插件都可以给你的项目添加一个仓库。内置的Gradle插件(如java-library )不会向你的项目添加资源库。
你要找的是通过jcenter() API以编程方式添加JCenter作为资源库的插件。
向团队查询
你可能在你的构建脚本或插件中找不到任何对JCenter的引用,但你可能仍然在使用JCenter。如果你有一个内部镜像或企业代理版本库,你需要检查该版本库是否使用JCenter。
对付费的JFrog云客户的影响可能不同,所以请直接联系JFrog,了解如果你的内部镜像是由JFrog提供的,你是否可以继续使用JCenter。
排除来自JCenter的依赖关系的故障
你可以使用gradle dependencies (或构建扫描)来确定哪些依赖关系没有解决,或者它们可能发生了什么变化。如果Gradle无法解决来自任何存储库的依赖关系,那么当解决错误时,Gradle的构建也会失败。
在下面的例子中,你可以看到Gradle在切换到Maven Central后,未能解析trove4j的依赖关系。
在控制台:
在构建扫描中:
此时,如果该包只在JCenter上可用,你的选择是。
- 等待维护者迁移到另一个资源库(如Maven Central)。
- 寻找另一个在Maven Central上可用的同等软件包
- 完全取消对该软件包的依赖
- 将该包复制到自己的内部仓库
如果你的构建能从另一个资源库解决大部分依赖,你可以继续使用JCenter来处理少数只在那里可用的包。你可以通过使用内容过滤器来防止那些只在JCenter上可用的新包被引入你的构建中。这可以防止Gradle在JCenter中寻找所有的包。
例如,许多Android项目依赖于Trove4J库,而在写这篇文章的时候,该库只在JCenter中可用。我们可以使用一个内容过滤器,只允许org.jetbrains.trove4j 组中的工件来自JCenter。 我们还把jcenter() 放在最后,这样Maven Central就会被首先搜索到。
repositories {
mavenCentral()
jcenter {
content {
// org.jetbrains.trove4j is only available in JCenter
includeGroup("org.jetbrains.trove4j")
}
}
}
对Gradle插件的影响
在幕后,Gradle Plugin Portal使用JCenter来解决插件的依赖关系。在最终关闭之前,我们将把插件门户从JCenter迁移出去。在Plugin Portal从JCenter迁移的过程中,Build将不需要做任何改变。
解决现有插件的问题
现有的插件将继续以相同的方式解决。 不需要对你的构建进行修改。
发布新的或更新的插件
如果你正在发布你的插件,com.gradle.plugin-publish ,你就不会受到影响。 只要仔细检查你的构建没有直接使用JCenter。
如果你正在发布你的插件到Bintray,你将需要使用com.gradle.plugin-publish 插件来发布你的插件的新版本。你越早做到这一点越好。如果你有疑问或问题,我们可以提供帮助。
我们将在2021年3月31日自动迁移所有发布到Bintray的插件。在该日期之后,我们将不再同步发布到Bintray的插件。这种迁移对于解决依赖关系的用户来说应该是透明的。
对发布到Bintray的软件包的影响
如果你使用com.jfrog.bintray插件发布你的构建到Bintray,你需要找到另一个仓库来托管你的包。你也许可以使用内置的maven-publish 。
如果你要迁移到Maven Central,io.github.gradle-nexus.publish-plugin插件可以自动发布到Nexus和Maven Central。
安全方面的考虑
从JCenter迁移到另一个仓库之前,你应该考虑一些安全问题。
正如我们近年来看到的,依赖关系混乱和命名空间碰撞会对供应链攻击造成严重危险。这些漏洞中的每一个都依赖于不受信任的工件被用来代替受信任的工件。
当你改变你用来解决依赖关系的存储库列表时,你可能会无意中把自己暴露在这些类型的攻击中。
例如,假设你有一个使用JCenter和另一个不太受欢迎的仓库(又称LessPopularCenter)来解决依赖关系的构建(按这个顺序),而你的构建有一个对com.example:foo:1.0 的依赖。包com.example:foo 只发布在 JCenter 上,但有人设法将com.example:foo:1.0 的副本放在 LessPopularCenter 上。只要JCenter是Gradle检查依赖关系的第一个地方,你的构建就会一直得到官方软件包。
如果你删除JCenter,用Maven Central代替(Maven Central没有com.example:foo 的副本),你的构建可能仍然能够解决com.example:foo ,因为LessPopularCenter有它的副本。不幸的是,我们不能保证LessPopularCenter上的副本与官方软件包相同。
如果你想有力地保证你现在依赖的工件是相同的或来自同一个受信任方,你应该启用依赖性验证。一旦启用,Gradle会自动对所有从资源库解析的依赖关系进行依赖性验证。这将帮助你检测到依赖的工件的意外变化、受损的工件或新的不可信任的工件来源。
依赖性验证需要一些前期的设置。你需要指定一个受信任的密钥列表,以便在验证签名的工件时使用。对于未签名的工件,你需要为每个工件指定预期的校验和。
依赖性验证失败并不一定意味着发生了邪恶的事情。依赖性元数据和工件是混乱的。有时有合法的理由让一个包在同一版本的两个存储库中有不同的工件。如果该软件包被分别发布到JCenter和Maven Central,它可能被构建了两次,并产生了行为相同的不同工件。这意味着,即使你从两个仓库解析了 "相同 "的版本,当你逐个比较工件时,你会得到不同的结果。在这种情况下,你可以告诉Gradle接受两个校验和为有效。
反馈意见
如果你有任何问题,请在我们的论坛或Gradle社区Slack上告诉我们。