Maven:确保在多项目开发中使用相同的主要父 pom 版本

标签 maven maven-dependency maven-enforcer-plugin

我们的团队有多个项目;大多数项目只是库。为简单起见,让我们假设这些库不相互依赖,并且有一个使用它们的项目,例如:

Project Main:
    Project Lib-A:
        X (3rd-party library)
    Project Lib-B:
        X (3rd-party library)

为了避免在“Main”中出现意外,我们希望确保我们自己的所有项目都使用相同版本的 3rd-party 库,以便例如'Lib-A' 和 'Lib-B' 都是使用相同版本的库 X 构建和测试的。

为了实现这一点,我们使用 父 pom <dependencyManagement>部分详细介绍了所有相关 3rd-party 库的版本及其传递依赖项。这个父 pom 被所有项目继承,即上面示例中的“Main”、“Lib-A”和“Lib-B”。那么每个子 pom 只会使用 <dependency>不指定任何版本。我们还有maven enforcer plugin's dependencyConvergence rule确保我们没有错过任何项目中的任何库冲突。

问题:增加X版本 : 'Lib-A' 的开发者将 X 的版本从 1.0 增加到 2.0。因此,他更改了父 pom 中 X 的版本,增加了父 pom 的版本,释放了父 pom,并通知来自“Main”的人他们现在应该使用新的父 pom。情况变成这样:
Main - inherits from Parent:2.0 and depends on:
    Lib-A:2.0 - inherits from Parent 2.0 and depends on X:2.0
    Lib-B:1.0 - inherits from Parent 1.0 and depends on X:1.0
    X:2.0 (taken from Parent:2.0 <dependencyManagement> section)

一切,包括“Main”,构建良好,“maven 执行器插件”没有检测到任何冲突,因为 X 的版本在“Main”继承的 Parent:2.0 中明确指定。 所以我们发布'Main'。

糟糕... . Lib-B 从未使用 X:2.0 构建。它有很好的单元测试可以发现问题,但我们从未尝试过。我们忘记更新 Lib-B,尝试使用 X:2.0 并发布它。 'Main' 的构建仍然没有问题,并且 maven 执行器插件从未提示过。

问题 :我们需要 maven 来检测是否存在 的依赖项继承来自相同的 Artifact 但不同的主要版本并且构建失败。
在我们的例子中,构建必须失败,因为 'Main' 和 'Lib-A' 继承自 Parent:2.0,但 'Lib-B' 继承自 Parent:1.0。

到目前为止我的解决方案(黑客) : 除了继承之外,添加显式依赖于父pom 所有项目 (即“主要”、“Lib-A”和“Lib-B”):
<dependency>
    <artifactId>Parent</artifactId>
    <type>pom</type>
    <version>${project.parent.version}</version>
</dependency>

然后使用 <bannedDependencies> Maven 执行器插件规则 禁止其他主要父版本 (我们也可以使用它的 <dependencyConvergence/> 规则,如果我们想即使在轻微的父版本冲突中也失败)。

在父 pom 的主要版本冲突时,是否有一种不那么笨拙和麻烦的方法来失败?可能是我们管理 Maven 依赖项的整个方法是错误的,那么推荐的方法是什么?

更新 :
尝试按照@JF Mayer 的建议和描述为 maven-enforcer-plugin 编写我自己的规则 here ,在放弃之前。原因:
  • 首先,从依赖项中无法获得父pom信息,至少从maven's DependencyGraphBuilder构建的节点中无法获得。
  • 好的,我已经将我的父 poms 添加为 child 的显式依赖项,并尝试使用这个 DependencyGraphBuilder检测对具有不同主要版本的父级的依赖关系。 没门! 正如 mvn dependency:tree 所见也使用这个类,DependencyGraphBuilder不提供所有依赖项,因此不能用于检测依赖项冲突。这就是为什么<dependencyConvergence> maven 执行者规则正在使用一个 super 弃用的 DefaultDependencyTreeBuilder甚至已从 GitHub 和其他任何地方删除 - 对于无故障的自定义解决方案来说,这不是一个好的选择。
  • 最佳答案

    为了完整起见,我自己的穷人的解决方案:

  • 将 pom 类型的显式依赖项添加到每个项目的父级,以便 maven-enforcer-plugin 的 <dependencyConvergence>规则将检测冲突的父版本。这个没有什么大不了的,因为我们只添加了一次这一部分,然后就忘记了:
    <dependency>
        <groupId>${project.parent.groupId}</groupId>
        <artifactId>${project.parent.artifactId}</artifactId>
        <version>${project.parent.version}</version>
        <type>pom</type>
    </dependency>
    
  • <dependencyConvergence>即使在父版本中的“增量”差异上,“Main”上的构建也会失败,例如1.0.1 和 1.0.2。在这种情况下,“Main”的开发人员可以决定尽管存在父版本冲突,也可以构建它,因为它无关紧要(这是我最初的问题)。所以他用一些特殊的配置文件构建了'Main',排除了对父级的依赖:mvn -P I-know-what-I-am-doing deploy .

  • 我对这个解决方案不是很满意,因为第 2 步要求“Main”的开发人员在父版本冲突的情况下使用特殊的配置文件来构建它。我更喜欢一个解决方案,它总是在主要的父版本冲突中失败,但会自动忽略父 pom 版本中微不足道的差异,我只是不知道如何实现这一点。

    关于Maven:确保在多项目开发中使用相同的主要父 pom 版本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61796353/

    相关文章:

    spring 版本 3.2.0 的 spring 测试失败 : Failed to load ApplicationContext

    maven避免下载依赖

    java - 从 Maven 项目的类路径中排除某些依赖项

    java - Java Library编译后如何使用?

    java - 运行 `mvn deploy` 时如何使用 Jenkins 凭据?

    maven-enforcer-plugin 和子 pom

    Maven Enforcer 插件 : Specify rules via command line

    Maven 依赖项 - 版本与更新

    java - 添加依赖到 pom.xml 文件后 Spring Tool Suite 自动关闭

    maven - 如何禁止版本包含特定部分的 Maven 依赖项?