关于大型项目的版本控制和避免包含表达式的版本的 Maven 建议

Posted

技术标签:

【中文标题】关于大型项目的版本控制和避免包含表达式的版本的 Maven 建议【英文标题】:Maven advice relating to versioning of a large project and the avoidance of versions containing expressions 【发布时间】:2012-02-14 23:09:54 【问题描述】:

我正在考虑重组一个大型 Maven 项目...

我们当前结构的基本概述:

build [MVN plugins, third party dependency management]:5.1
   NRW Utils:6.0.0.0-beta12-SNAPSHOT
      server-utils:6.0.0.0-beta12-SNAPSHOT
      ... 
   CMW Root:6.0.0.0-beta12-SNAPSHOT
      cmw-webapp:6.0.0.0-beta12-SNAPSHOT
      cmw-core [dependencies on NRW Utils]:6.0.0.0-beta12-SNAPSHOT
      ...
   NRW Root :6.0.0.0-beta12-SNAPSHOT
      nrw-webapp [depends on NRW Utils & CMW Root modules]:6.0.0.0-beta12-SNAPSHOT
      ...

改变的原因:

每个集合模块(即 NRW Utils、CMW Root 和 NRW Root)的大小越来越大,构建过程开始花费大量时间(有时约 4 小时)。

新计划:

build [MVN plugins, third party dependency management]:5.1
   NRW Utils:6.0.0.0-NU-beta4-SNAPSHOT
      server-utils:6.0.0.0-NU-beta4-SNAPSHOT
      ... 
   CMW Root:6.0.0.0-CMW-beta12-SNAPSHOT
      cmw-webapp:6.0.0.0-CMW-beta12-SNAPSHOT
      cmw-core [dependencies on NRW Utils]:6.0.0.0-CMW-beta12-SNAPSHOT
      ...
   NRW Root :6.0.0.0-NRW-beta9-SNAPSHOT
      nrw-webapp [depends on NRW Utils & CMW Root modules]:6.0.0.0-NRW-beta9-SNAPSHOT
      ...  

我们已经开始在版本中引入“键”来区分不同的“集合模块”,因此可以轻松执行分步发布。此外,我们的实用程序模块更加稳定,因此我们可能不需要那么多的 beta 版本 - 现在对保持 beta 编号同步没有任何限制。

还值得注意的是,实际上有 5 个不同的“集体模块”(不仅仅是 3 个)都使用不同的版本(通过唯一键区分)构建,这就是为什么我认为最好有一个版本的集中位置,而不是 5 个不同 POM 中的重复属性。

现在问题在于在不同版本的不同“集合模块”中定义对模块的依赖关系时 POM 文件的内容。

建议的依赖版本管理解决方案:

build [MVN plugins, third party dependency management]:5.1
   nrw-version-management:6.0.0.0-beta-SNAPSHOT
      [contains properties defining latest versions of each collective module]   
      NRW Utils:6.0.0.0-NU-beta4-SNAPSHOT
         server-utils:6.0.0.0-NU-beta4-SNAPSHOT
         ... 
      CMW Root:6.0.0.0-CMW-beta12-SNAPSHOT
         cmw-webapp:6.0.0.0-CMW-beta12-SNAPSHOT
         cmw-core [dependencies on NRW Utils]:6.0.0.0-CMW-beta12-SNAPSHOT
         ...
      NRW Root :6.0.0.0-NRW-beta9-SNAPSHOT
         nrw-webapp [depends on NRW Utils & CMW Root modules]:6.0.0.0-NRW-beta9-SNAPSHOT
         ... 

nrw-version-management (pom.xml):

...
<parent>
    <groupId>com.project</groupId>
    <artifactId>build</artifactId>
    <version>5.1</version>
</parent>
<groupId>com.project</groupId>
<artifactId>nrw-versions-manager</artifactId>
<version>6.0.0.0-beta-SNAPSHOT</version>
<name>Version Maven Properties</name>
<description>A centralised place for all module property versions</description>
<packaging>pom</packaging>
<properties>
    <nrw.utilities.version>6.0.0.0-NU-beta4-SNAPSHOT</nrw.utilities.version>
    <nrw.cmw.version>6.0.0.0-CMW-beta12-SNAPSHOT</nrw.cmw.version>
    <nrw.version>6.0.0.0-NRW-beta9-SNAPSHOT</nrw.version>
</properties>
...

CMW 根 (pom.xml):

...
<parent>
    <groupId>com.project</groupId>
    <artifactId>nrw-versions-manager</artifactId>
    <version>$nrw.core.version</version>
    ...
</parent>
<groupId>com.project</groupId>
<artifactId>CMW-root</artifactId>
<version>6.0.0.0-CMW-beta12-SNAPSHOT</version>
<packaging>pom</packaging>
<dependencyManagement>
    <dependencies>
        ...
        <dependency>
            <groupId>$project.groupId</groupId>
            <artifactId>server-utils</artifactId>
            <version>$nrw.utilities.version</version>
        </dependency>
        ...
</dependencyManagement>
<profiles>
    <profile>
        <id>all</id>
        <modules>
            <module>cmw-webapp</module>
            <module>cmw-core</module>
            ...
        </modules>
    </profile>
    ...
</profiles>
...

注意然后,属性 $nrw.core.version 将通过命令行参数(或默认属性值)设置为 6.3.0.0-beta-SNAPSHOT 以进行快照构建。

可能的发布过程(针对 6.0.0.0):

    如果尚未构建,请构建 5.1 构建模块 构建 nrw-version-management 6.0.0.0(以避免快照依赖 - 但尚未更改任何属性) 构建 NRW 实用程序 6.0.0.0-NU cmd 参数:-Dnrw.core.version=6.0.0.0 构建 CMW 根 6.0.0.0-CMW cmd参数:-Dnrw.core.version=6.0.0.0 -Dnrw.utilities.version=6.0.0.0-NU 构建 NRW 根 6.0.0.0-NRW cmd参数:-Dnrw.core.version=6.0.0.0 -Dnrw.utilities.version=6.0.0.0-NU -Dnrw.cmw.version=6.0.0.0-CMW 为存储库重新构建 nrw-version-management 6.0.0.0 cmd参数:-Dnrw.core.version=6.0.0.0 -Dnrw.utilities.version=6.0.0.0-NU -Dnrw.cmw.version=6.0.0.0-CMW 使用新的开发版本构建 nrw-version-management 6.1.0.0-beta-SNAPSHOT 并更新 POM 文件

问题:

构建过程似乎很冗长,尤其是与 nrw-version-management 模块有关。 另外,我开始看到这个警告:

'version' 包含一个表达式,但应该是一个常量

在进行了一些调查后,我现在了解到在设置版本时(指定父 POM 时)不建议使用表达式:

Warning on using project.parent.version as the version of a module in Maven 3 Maven: property substitution not done for /project/version tag of pom? http://maven.40175.n5.nabble.com/Pom-Parent-Version-Properties-td124576.html

问题:

我可以忽略这个警告吗?一些帖子开始建议使用属性指定父 POM 版本可能是可以接受的。 这种通用方法是传统方法吗?还是有缺陷? 是否有更好的解决方案来解决这个不断发展的项目的重组问题?

提前致谢。

【问题讨论】:

【参考方案1】:

为所有子模块使用一个版本的好处是简单,这一好处不应被低估。

您确实应该多次问自己是否真的要依赖同一层次结构中的不同版本的模块。正如您指出的那样,发布变得很麻烦。

通过使用单一版本以标准化方式处理关系并在成功构建后部署到本地存储库,您应该能够按照预期的方式享受依赖管理。

如果您重组项目以使其符合发布插件的约定,发布就变得轻而易举。

【讨论】:

感谢您的意见。我们放弃单一版本的原因是没有这种限制,将我们的构建分解成“bitesize”块会容易得多,而且还具有简单的额外好处;如果一个模块有更新,我们现在不需要重新构建所有内容。尽管只有一个版本,但还有更多的想法/方法吗?谢谢。 您可以通过为您的工件共享一个 repo 来获得一口大小的块。诚然,当您更新版本号时,您必须构建整个项目,但之后您只构建和部署有任何开发的模块。 /奥斯卡 嗯 - 但我们已经在使用构建工件的存储库。将构建保留在单个版本上仍然意味着我们必须将项目构建为一个版本,这给我们留下了耗时的构建过程(4 小时)。此外,我们的版本号经常更改(当只有某些模块会导致这种情况时)。 但是如果您开始使用不同版本的子模块,您将陷入依赖管理的噩梦......【参考方案2】:

正如 nico_ekito 在其中一个 cmets 中所说,在我看来,您现在正陷入“依赖管理的噩梦”。根据您的情况...管理子模块的不同版本(以及不同的代码稳定性)是否表明这些子模块不再是大项目的一部分?

我的意思是,作为人类,我们可以清楚地表明这些模块是全局的一部分,是解决问题的整个方法。当您发现您的实用程序类在大图范围之外没有用处时,这是很常见的。但是,从 Maven 的角度来看,我认为您实际上是在处理不同的项目,而不是一个大项目的模块。

因此,也许值得将代码库分离为不同的结构,只需简单地从实际需要它的模块中引用实用程序 jar,并使用稳定的构建而不是“该依赖项的最新版本”。如果使用稳定的构建是不可行的,因为即使该依赖项的代码非常稳定,它也会与其他模块的代码同时发生变化,那么 Maven 为您提供的解决方案就是使用 SNAPSHOTS。

我认为将代码库分解为单独的项目时会有一些好处:

这样 Maven 就不会在不需要时触发这些实用程序模块中的构建。 如果能找到一种方法,只为依赖项使用稳定版本,您将避免很多麻烦。 您还可以拆分团队,让那些仅使用实用程序 jar 的团队在使用该依赖项的团队的“需求不足的基础上”这样做。 如果这些实用程序足够抽象或可重用,那么有一天您可能会发现另一个项目也可以使用它们,而无需从更大的项目中引用子模块。

互联网上有很多关于Maven handles dependencies(和其他事情)方式的讨论,很多人抱怨你面临的同样问题。在我自己看来,Maven 是一个很棒的工具,旨在为我们在开始新项目时节省大量时间,但有时它可能有点麻烦。我开始查看其他工具,例如Gradle,但现在更改构建工具可能更糟糕。只是考虑打破代码库的想法,有时我们可以通过一点“项目管理”(或本例中的“组合管理”)来解决“软件问题”。

【讨论】:

【参考方案3】:

考虑到现在构建过程需要很长时间(前几天它在 7 小时后失败!!),我认为在这个阶段在整个项目中坚持单一版本是不可行的。

但是,下面的两个链接并没有完全回答我的问题,但正在到达那里:

How to share common properties among several maven projects? How do I tell Maven to use the latest version of a dependency?

【讨论】:

以上是关于关于大型项目的版本控制和避免包含表达式的版本的 Maven 建议的主要内容,如果未能解决你的问题,请参考以下文章

聊聊Spring Cloud版本的那些事儿

ios开发怎么查找ios工程的版本号

语义版本控制问题和 npm 5 或更高版本

如何避免在版本控制中存储密码?

项目SVN版本管理与大型代码上线方案

关于 Git 的基础知识可能你还不知道