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 构建初始化插件生成使用 JCenter 存储库解析依赖项的构建模板。在许多代码示例和文档中,JCenter 都用作示例存储库。
你的构建很可能依赖于 JCenter。我们已在 GitHub 上发现超过一百万个使用 JCenter 和 Gradle 的 Git 存储库。
为了阻止新项目使用 JCenter,我们将从我们的示例和初始化模板中删除 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 运行自己的公共存储库。这也会受到关闭的影响。你应该检查是否正在使用以 dl.bintray.com 开头的 URL 的存储库。由于这些存储库可以包含任何内容,你需要找出你从这些存储库中使用的依赖项以及它们可能迁移到哪里。
检查你的构建扫描 #
如果你正在使用 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 可用。我们可以使用内容过滤器来仅允许 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 插件门户使用 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,但其他人设法在 LessPopularCenter 上放置了 com.example:foo:1.0
的副本。只要 JCenter 是 Gradle 检查依赖项的首选位置,你的构建将始终获得官方包。
如果你删除 JCenter 并将其替换为 Maven Central(它没有 com.example:foo
的副本),你的构建可能仍然能够解析 com.example:foo
,因为 LessPopularCenter 有它的副本。不幸的是,无法保证 LessPopularCenter 上的副本与官方包相同。
如果你希望获得强有力的保证,即你现在依赖的构件是相同的或来自相同的受信任方,你应该启用依赖验证。启用后,Gradle 会自动对从存储库解析的所有依赖项执行依赖验证。这将帮助你检测依赖项构件的意外更改、受损构件或新的不受信任的构件源。
依赖验证需要一些前期设置。你需要指定要用于验证签名构件的受信任密钥列表。对于未签名构件,你需要为每个构件指定预期的校验和。
依赖验证失败不一定意味着发生了恶意事件。依赖元数据和构件很混乱。有时,包从两个存储库为同一版本提供不同构件是合理的。如果包分别发布到 JCenter 和 Maven Central,它可能已被构建两次并生成了行为相同的不同构件。这意味着即使你从两个存储库解析“相同”的版本,当你逐字节比较构件时,你也会得到不同的结果。在这种情况下,你可以告诉 Gradle接受两个校验和都有效。
反馈 #
如果您有任何问题,请在我们的论坛或Gradle 社区 Slack上告知我们。