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

Posted

技术标签:

【中文标题】Maven:在多项目开发中确保相同的主要父 pom 版本【英文标题】:Maven: ensure same major parent pom version in multi-project development 【发布时间】:2020-08-30 22:16:48 【问题描述】:

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

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

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

为了实现这一点,我们使用带有<dependencyManagement> 部分的父pom,详细说明了所有相关第3 方库的版本以及它们的传递依赖项。这个父 pom 被所有项目继承,即上面示例中的 'Main'、'Lib-A' 和 'Lib-B'。然后每个子 pom 将只使用 <dependency> 而不指定任何版本。我们也有maven enforcer plugin's dependencyConvergence rule 以确保我们没有错过任何项目中的任何库冲突。

问题:增加 X 的版本:“Lib-A”的开发者将 X 的版本从 1.0 增加到 2.0。所以他在父 pom 中更改 X 的版本,增加 parent 的版本,释放父 pom,并通知来自“Main”的人他们现在应该使用新的父级。情况变成这样:

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 enforcer plugin”没有检测到任何冲突,因为 X 的版本在 Parent:2.0 中明确指定,“Main”从该版本继承。 所以我们发布了“Main”。

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

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

到目前为止我的解决方案(一个 hack):除了继承之外,添加对父 pom 的显式依赖到所有项目(即'Main',' Lib-A' 和 'Lib-B'):

<dependency>
    <artifactId>Parent</artifactId>
    <type>pom</type>
    <version>$project.parent.version</version>
</dependency>

然后使用 maven enforcer 插件的&lt;bannedDependencies&gt; 规则禁止其他主要的父版本(如果我们想在轻微的父版本冲突中失败,我们也可以使用它的&lt;dependencyConvergence/&gt; 规则)。

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

更新: 在放弃之前,尝试按照@JF Mayer 的建议和描述here 为maven-enforcer-plugin 编写我自己的规则。原因:

    首先,从依赖项中无法获得父pom信息,至少无法从maven's DependencyGraphBuilder构建的节点中获得 好的,我已将我的父 pom 作为显式依赖项添加到子项,并尝试使用此DependencyGraphBuilder 来检测对具有不同主要版本的父项的依赖项。 没办法! 从同样使用此类的mvn dependency:tree 可以看出,DependencyGraphBuilder 不提供所有依赖项,因此它不能用于检测依赖项冲突。这就是为什么 &lt;dependencyConvergence&gt; maven 强制执行规则使用已被超级弃用的 DefaultDependencyTreeBuilder,它甚至已从 GitHub 和其他任何地方删除 - 对于无故障的自定义解决方案来说,这不是一个好的选择。

【问题讨论】:

您是否考虑过将所有库一起构建在一个多模块项目中? 不,这根本不是一个选项。首先,代码库非常大。其次,实际上有不止一个“主要”项目。我只是试图简化问题。 那么我建议你为 Maven 执行器插件编写自己的执行器规则。 非常有趣,谢谢!我们可能会这样做。奇怪的是,我们的问题似乎如此普遍,但我们最终可能会编写自定义 maven 规则。 “首先,父pom信息不可用”——为什么会出现问题?只需在构建阶段将其添加到元中,当它可用时。如果您在根项目(jar 插件)中描述默认插件配置,这应该是微不足道的。然后自定义实施者插件规则将起作用。 【参考方案1】:

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

    将 pom 类型的显式依赖添加到每个项目的父级,以便 maven-enforcer-plugin 的 &lt;dependencyConvergence&gt; 规则检测到冲突的父级版本。这个没什么大不了的,因为我们只添加了一次就忘记了它:

    <dependency>
        <groupId>$project.parent.groupId</groupId>
        <artifactId>$project.parent.artifactId</artifactId>
        <version>$project.parent.version</version>
        <type>pom</type>
    </dependency>
    
    &lt;dependencyConvergence&gt; 即使在父版本中的“增量”差异上也将无法在“主”上构建,例如1.0.1 和 1.0.2。在这种情况下,“Main”的开发人员可以决定尽管父版本冲突,但可以构建它,因为它无关紧要(这是我最初的问题)。 因此,他使用一些特殊配置文件构建了“Main”,排除了对父级的依赖:mvn -P I-know-what-I-am-doing deploy

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

【讨论】:

【参考方案2】:

我认为您正在寻找的是 Reactor Module Convergence 执行器:

https://maven.apache.org/enforcer/enforcer-rules/reactorModuleConvergence.html

它与依赖收敛规则不同。

【讨论】:

以上是关于Maven:在多项目开发中确保相同的主要父 pom 版本的主要内容,如果未能解决你的问题,请参考以下文章

Maven学习小结(四 聚合与继承)

Maven - 跳过父项目构建

maven如何继承父工程的依赖关系

如何正确导入 Maven 项目到 Eclipse?

多个项目的 Maven 依赖项与依赖项管理

maven项目的继承