JCenter 关闭对 Gradle 构建的影响
目录
简介
ℹ️ 2024 年 7 月 15 日更新 |
---|
请参阅 我们最近的博文,了解关于插件门户和 JCenter 的最新信息。 |
2021 年 2 月 3 日,JFrog 宣布他们将关闭 Bintray 和 JCenter。这篇文章告诉您需要了解和采取哪些措施,以避免对您的构建管道造成中断。
您的构建可能会受到此次关闭的多种方式的影响
此外,您应该注意从一个仓库迁移到另一个仓库时的 安全注意事项。
更新:JFrog 已决定无限期地将 JCenter 保留为只读仓库。JCenter 不再接受新的软件包和版本。所有 Bintray 服务均已关闭。
背景 #
JCenter 是一个中央构件仓库,类似于 Maven Central。软件项目使用 JCenter 将他们的软件分发给其他人。JCenter 也充当 Maven Central 的镜像,因此 Maven Central 上可用的任何依赖项在 JCenter 上也可用(但反之则不然)。
Bintray 是一个管理层,软件项目使用它来发布和推广软件包到 JCenter。Bintray 还允许用户创建与 JCenter 隔离的公共用户特定仓库。
这些服务都受到了关闭的影响。
对构建的影响 #
默认情况下,Gradle 不会向您的项目添加构件仓库;但是,Gradle 确实提供了一个 便捷的 API 用于使用 JCenter 仓库。
Gradle Build 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()
方法将在下一个主要版本中删除。
托管在 JCenter 上的软件包需要在 2021 年 3 月 31 日之后找到替代仓库来提供更新。许多软件包可能会迁移到 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。如果您正在使用插件门户(通过 gradlePluginPortal()
或 URL plugins.gradle.org/m2)来解析您的应用程序的依赖项,您可能依赖于 JCenter。您应该避免将插件门户用作仓库,除非是 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 Cloud 客户的影响可能有所不同,因此请直接联系 JFrog 以了解如果您的内部镜像由 JFrog 提供,您是否可以继续使用 JCenter。
解决来自 JCenter 的依赖项问题 #
您可以使用 gradle dependencies
(或构建扫描)来确定哪些依赖项未被解析或它们可能发生了怎样的变化。如果 Gradle 无法从任何仓库解析依赖项,构建也会因解析错误而失败。
在下面的示例中,您可以看到在切换到 Maven Central 后,Gradle 无法解析 trove4j 依赖项。
在控制台中:
在构建扫描中:
此时,如果该软件包仅在 JCenter 上可用,您的选择是
- 等待维护者迁移到另一个仓库(例如,Maven Central)
- 找到另一个在 Maven Central 上可用的等效软件包
- 完全删除您对该软件包的依赖
- 将软件包复制到您自己的内部仓库
如果您的构建可以从另一个仓库解析其大部分依赖项,您可以继续使用 JCenter 来处理少数仅在那里可用的软件包。您可以使用 内容过滤器,防止仅在 JCenter 上可用的新软件包被引入到您的构建中。这可以防止 Gradle 在 JCenter 中查找所有软件包。
例如,许多 Android 项目依赖于 Trove4J 库,在撰写本文时,该库仅可从 JCenter 获得。我们可以使用 内容过滤器,仅允许来自 JCenter 的 org.jetbrains.trove4j
组中的构件。我们还将 jcenter()
放在最后,以便首先搜索 Maven Central。
repositories {
mavenCentral()
jcenter {
content {
// org.jetbrains.trove4j is only available in JCenter
includeGroup("org.jetbrains.trove4j")
}
}
}
对 Gradle 插件的影响 #
在幕后,Gradle 插件门户 使用 JCenter 来解析插件的依赖项。我们将在最终关闭之前将插件门户从 JCenter 迁移出来。在插件门户从 JCenter 迁移出来期间,构建无需进行更改。
解决现有插件 #
现有插件将继续以与今天相同的方式解析。您的构建无需进行任何更改。
发布新的或更新的插件 #
如果您正在使用 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(其中没有 com.example:foo
的副本),您的构建可能仍然能够解析 com.example:foo
,因为 LessPopularCenter 有它的副本。不幸的是,无法保证 LessPopularCenter 上的副本与官方软件包相同。
如果您想要强烈保证您现在依赖的构件是相同的,或者来自同一受信任方,您应该启用 依赖项验证。启用后,Gradle 会自动对从仓库解析的所有依赖项执行依赖项验证。这将帮助您检测依赖项构件的意外更改、被破坏的构件或新的不受信任的构件来源。
依赖项验证需要一些前期设置。您需要指定一个受信任密钥列表,用于验证签名的构件。对于未签名的构件,您需要为每个构件指定预期的校验和。
依赖项验证失败并不一定意味着发生了邪恶的事情。依赖项元数据和构件很混乱。有时,对于同一版本的软件包,来自两个仓库的构件不同是有合法原因的。如果软件包分别发布到 JCenter 和 Maven Central,则它可能被构建了两次,并生成了行为相同的不同构件。这意味着即使您从两个仓库解析“相同”版本,当您逐字节比较构件时,您也会得到不同的结果。在这种情况下,您可以告诉 Gradle 接受两个校验和都有效。
反馈 #
如果您有任何问题,请在我们的 论坛 或 Gradle 社区 Slack 上告知我们。