如何确定升级依赖项是不是会破坏 jar 文件?
Posted
技术标签:
【中文标题】如何确定升级依赖项是不是会破坏 jar 文件?【英文标题】:How can I determine if upgrading a dependency will break a jar file?如何确定升级依赖项是否会破坏 jar 文件? 【发布时间】:2018-07-07 15:41:31 【问题描述】:ore.spongepowered.org 是一个托管 Minecraft 插件的网站。
这些插件依赖于一个名为 SpongeAPI 的依赖项才能运行。
给定一个已上传到我们服务的 jar 文件,并且具有将其与 SpongeAPI 的给定(semver)依赖相关联的元数据,我们如何确定 SpongeAPI 中是否存在影响给定插件的二进制不兼容更改?
例如为 API 版本 5 发布了一个插件 jar。
API 5.1 (semver) 已发布,它仅包含新增内容。只要 semver 被强制执行,由于版本控制约定,我们知道该插件可能会工作。
API 6 发布,它是一个 semver 主要版本,但 jar 是针对 API5 构建的,插件有可能仍然兼容,但不能保证。我们如何测试(使用工具)插件是否引用了已删除的代码或其签名从 API 5 -> API 6 更改?
知道这一点很有价值,因为我们可以在人们使用可能不兼容的组合时发出警告。
注意:我们控制的是 Library SpongeAPI,而不是社区制作的插件。
【问题讨论】:
全面的测试覆盖率? 运行集成测试套件。 请注意,“API 5.1”和“API 6”不包含符合 SemVer 的版本字符串。 完整版本字符串为 API 5.1.0 和 6.0.0 【参考方案1】:传统的方法是使用自动构建和持续集成工具(如 Jenkins、Bitbucket Pipelines、Gitlab-CI 等)来构建系统(我假设您已经在使用 Maven 或 Gradle,因为您已经在问题中标记了它们)。
如果更改(到较新的依赖项)更改了方法签名或其他重构等任何内容,则构建将失败。
此外,您还应该进行单元测试,以确保您的功能按预期工作。如果底层库的基本行为发生变化而影响您的功能,您也可以检测到这一点。这将帮助您捕捉功能变化,而不仅仅是编译问题。
最后,您可能想看看新的 Java 9 模块系统。在采用方面它仍然有点落后,但它可能会为您正在寻找的解决方案提供替代解决方案,特别是如果您也可以控制依赖项。
【讨论】:
问题是,这是人们上传的外部 jar,所以我们可以控制依赖关系,但不能控制人们上传的文件。此外,它们可能具有构建脚本未指定的其他依赖项、对其他插件的依赖项等。 插件是否有某种入口点?一些始终存在的标准接口?你能有一个自动化脚本,它试图用插件 Jar 针对你想要验证的 API 版本构建一个参考项目吗?然后作为一个额外的步骤调用标准入口点的方法作为一个非常基本的集成测试来检查插件是否按预期初始化?如果您使用 Maven / Gradle,其他依赖项不应该成为问题,它也会在构建您的测试项目时下载它们。 确实如此,但我将其视为完全外部的东西。由于执行该代码可能会给您带来更多问题,例如让服务器受到损害。我正在考虑类似于静态链接器或某种分析器的东西。 如果您可以访问插件的源代码,您可以从它的 repo 中提取并构建它(无需运行它)。如果已经编译了,那就有点挑战了,因为只有在调用缺失/修改的方法时才会得到NoSuchMethodError
。那是集成测试会有所帮助。我想你可以看看像 IntelliJ 这样的 IDE 如何对代码结构进行静态分析。您必须解码插件的类文件才能知道它们在内部调用了什么方法。
好的,如果您认为这是一种方法,请查看此列表以从某个地方开始,看看是否有任何工具适合您入门:en.wikipedia.org/wiki/…【参考方案2】:
即使依赖关系树中的每个组件都完全符合 SemVer 标准,您仍然需要带外(与 SemVer 相关)信息来关闭瞬态依赖关系。一般的依赖图,特别是菱形点依赖问题,都是已知的难题。测试可能会造成很小但非常昂贵的影响,但对于在具有数百或数千个组件的服务器上运行的任何重要产品通常是禁止的。
您能做的最好的事情就是将应用程序周围的环境容器化,并仅测试其中相关组件的有趣组合,仅发布那些通过您产品的整个测试套件的组合。然后你可以说“这是一个预先配置了我们的功能 X 的盒子,我们不声称与任何其他产品或组件版本的组合兼容”。特定于应用程序的 VM 最擅长将问题空间减少到经济可管理的表面。即使是像应用程序容器这样有点泄漏的环境也可以帮助驯服这只老虎。
【讨论】:
以上是关于如何确定升级依赖项是不是会破坏 jar 文件?的主要内容,如果未能解决你的问题,请参考以下文章
如何确定我的哪些依赖项依赖于我的 node_modules 中的特定包?