Maven中如何更新子模块的版本?
How to update the version of child modules in Maven?
如何更新子模块的版本?有很多像这样的 Whosebug 问题,但我找不到适合这种情况的问题...如果这是重复的,我会很高兴。
考虑以下项目。
parent
--mod1
--mod2
在开发发布周期开始时,我需要将父模块和模块更新到同一版本。如果父模块和模块的版本在整个发布过程中保持不变,那么我将只省略模块中的 <version>
标记并执行 versions:set -DnewVersion=1.1.1
以启动开发周期。但事实证明,这些模块并不是都以相同的版本结束循环。随着错误和修复的出现,只有那些有错误的模块才会得到更新。例如,parent 和 mod2 可能是版本 1.1.1-RC1,但 mod1 可能是 1.1.1-RC2。
因此我需要:
1) 在模块中包含一个 <version>
标签以独立跟踪每个模块版本。
2) 如果 mod2 需要 mod1 作为依赖项,我需要确保 mod2 引用最新版本的 mod1。
由此引出以下两个问题。
1) 在循环开始时,如何在一个 maven 命令中将父模块和模块设置为同一版本?我试过 version:set -DnewVersion=1.1.1
,但这只会更新所有 POM 的父版本,但不会更新模块的版本。我也试过 -N versions:update-child-modules
,但我认为我用错了,因为它什么都不做,只是显示所有模块都已跳过。
2) 这有点难,与上面的第 2 项匹配。如何一步更新 mod1 的版本和 mod2 对 mod1 版本的引用?我知道如何分两步完成:
父 pom:
<properties>
<!-- update this manually if mod1's version no longer matches parent -->
<mod1.version>${project.version}</mod1.version>
</properties>
mod2 pom:
<dependency>
<groupId>com.xxx</groupId>
<artifactId>mod1</artifactId>
<version>${mod1.version}</version>
</dependency>
当 mod1 升级到 1.1.1-RC2 时,我更新父 POM 和 mod1 POM 以反映这一点。这是两个步骤。无论如何把它变成一步?
我的例子很小,但在现实生活中有很多模块可以节省这个重要的时间,而且我很好奇。
1) 我过去也尝试过 version:set,但一直没能正常工作。它本应执行与 release:prepare 相同的过程,但实际上并非如此。所以你可以尝试的是mvn release:prepare -DautoVersionSubmodules -DdryRun
。这应该是在不检查任何内容到 repo 并且不制作任何标签的情况下进行所有更新。
2) 我相信 ClearTK 项目曾经遵循与您类似的策略:他们维护一个多模块项目,每个模块都有自己的发布周期。为了掌握情况,他们实施了一个自定义的 maven 插件来警告他们依赖版本不一致。
https://github.com/ClearTK/cleartk/tree/master/consistent-versions-plugin
虽然这样的插件不会进行您请求的更新,但它至少应该在需要更新时通知您。要真正解决您的问题,您可以考虑遵循与 ClearTK 相同的路线并实施您自己的 Maven 插件(或者您执行 ClearTK 最终完成的操作:切换到同步发布周期;))
好的,这就是我想到的。这是基于这篇 continuous-releasing-of-maven-artifacts 文章。
父 POM:
<properties>
<!-- versions of modules -->
<main.version>1.0</main.version>
<revision>SNAPSHOT</revision> <!-- default revision -->
<Module1.revision>${revision}</Module1.revision>
<Module2.revision>${revision}</Module2.revision>
<Module3.revision>${revision}</Module3.revision>
<Module4.revision>${revision}</Module4.revision>
<Module5.revision>${revision}</Module5.revision>
<Module1.version>${main.version}-${Module1.revision}</Module1.version>
<Module2.version>${main.version}-${Module2.revision}</Module2.version>
<Module3.version>${main.version}-${Module3.revision}</Module3.version>
<Module4.version>${main.version}-${Module4.revision}</Module4.version>
<Module5.version>${main.version}-${Module5.revision}</Module5.version>
</properties>
具有项目间依赖性的示例子 POM:
<groupId>com.xyz</groupId>
<artifactId>Module4</artifactId>
<packaging>jar</packaging>
<version>${Module4.version}</version>
<parent>
<groupId>com.xyz</groupId>
<artifactId>ParentProject</artifactId>
<version>1.0</version>
</parent>
<dependencies>
<dependency>
<groupId>com.xyz</groupId>
<artifactId>Module1</artifactId>
<version>${Module1.version}</version>
</dependency>
<dependency>
<groupId>com.xyz</groupId>
<artifactId>Module2</artifactId>
<version>${Module2.version}</version>
</dependency>
<dependency>
<groupId>com.xyz</groupId>
<artifactId>Module3</artifactId>
<version>${Module3.version}</version>
<type>jar</type>
</dependency>
<dependencies>
1) 在循环开始时,如何在一个 maven 命令中将父模块和模块设置为相同版本?
您不再需要。父 POM 可以保持相同的版本,只有在父 POM 更改时才会更改。在这种情况下,您可以使用 mvn version:set -DnewVersion=1.1.1
。但是您不需要使用这种方法。
相反,您可以使用 属性 main.version
动态设置版本。例如。 mvn clean deploy -Dmain.version=1.1.1
此外,要强制动态传递版本号,您可以省略我在上面的父 POM 中包含的默认值 main.version
属性。
2) 如何一步更新 mod1 的版本和 mod2 对 mod1 版本的引用?
这基本上归结为如何管理修订。如果我在 mvn 命令中不设置 revision
属性,那么所有模块将使用 SNAPSHOT
作为修订版。如果我将 revision
属性 设置为 RC1
那么所有模块都将获得该修订版。此外,如果我将 revision
设置为 RC1
,但将 Module4.revision
设置为 RC2
,则模块 4 获得 RC2,所有其他模块获得 RC1。这满足了客户对每个模块进行动态修订的要求。
这里有一些例子:
mvn clean deploy -Dmain.version=1.1.1
将所有模块设置为版本 1.1.1-SNAPSHOT
。
mvn clean deploy -Dmain.version=1.1.1 -Drevision=RC1
将所有模块设置为版本 1.1.1-RC1
。
mvn clean deploy -Dmain.version=1.1.1 -Drevision=RC1 -DModule4.revision=RC2
将所有模块设置为版本 1.1.1-RC1
,除了 Module4 设置为版本 1.1.1-RC2
.
有一个警告必须提及。如果将依赖模块(例如 Module1)的版本增加到 RC2,则还必须增加使用它的所有模块的版本,例如 Module4 也不能增加到 RC2(或下一个版本)。这是客户已经意识到的事情,也是我希望所有模块都具有相同版本的原因。但我真的很喜欢它的动态。基本上,现在通过命令行设置版本,无需更新 POM 文件。
1) 正如@rec 所说,maven 发布插件可以解决问题
$ mvn release:prepare -DautoVersionSubmodules=true
$ mvn release:perform
2) 您可以定义从 mod2 到 mod1 的依赖关系,例如:
<dependency>
<groupId>com.xxx</groupId>
<artifactId>mod1</artifactId>
<version>LATEST</version>
</dependency>
更多信息:How do I tell Maven to use the latest version of a dependency?
我测试了这两种解决方案并且有效!希望对你有帮助:)
问题 1)
管理应用程序生命周期和发布的最佳方式是使用发布插件。
您可能知道,Maven 的哲学是约定优于配置。 Maven 惯例是在开发期间使用快照版本(以 -SNAPSHOT 结尾的版本)并仅为发布分配非快照版本。
假设您正在开发 1.1.1 版。在开发过程中,您只需使用 1.1.1-SNAPSHOT。 Maven 将负责快照的更新。如果使用工件存储库,您可以使用 -U 来确保您始终拥有最新版本的快照。
发布准备就绪后,发布插件会生成并部署版本 1.1.1,并使用新的开发版本更新 POM,例如 1.1.2-SNAPSHOT。
关于多模块项目,有两种情况:模块相关但独立(例如多个Web应用程序)或者它们是单个大型应用程序或库的模块并且它们共享版本。你似乎对后者感兴趣。
在这种情况下最好的方法就是继承相同的 parent(也可能是 root)模块,包括它的版本。您引用 parent group:artifact:version 并且没有指定 children 的版本。通常你也继承组,所以你的 child pom 可以看起来像:
<parent>
<groupId>com.mycompany.myproject</groupId>
<artifactId>myproject-parent</artifactId>
<version>1.1.1-SNAPSHOT</version>
<relativePath>../myproject-parent</relativePath>
</parent>
<artifactId>myproject-module1</artifactId>
现在您只需要在发布插件的帮助下处理 children 指向 parent 的正确版本。
为了帮助它了解 children,您应该通过包含模块部分使您的 parent pom 也成为根 pom,如下所示。
问题2)
我通常在 parent 中声明属性,其中包含可能引用的所有工件的所有版本。如果几个模块共享版本,你只需要一个属性。 parent 可以看起来像:
<groupId>com.mycompany.myproject</groupId>
<artifactId>myproject-parent</artifactId>
<version>1.1.1-SNAPSHOT</version>
<packaging>pom</packaging>
<properties>
<myproject.version>1.1.1-SNAPSHOT</myproject.version>
</properties>
.......
<modules>
<module>../myproject-module1</module>
...
</modules>
Children可以使用
引用其他模块
<version>${myproject.version}</version>
使用 LATEST 声明依赖项是一种非常糟糕的做法。假设您为版本 1.1.1 执行此操作。现在您正在使用 1.1.2-SNAPSHOT 版本,并且您可能在本地存储库中安装了此版本的工件。
现在说由于某种原因您需要重建版本 1.1.1,例如因为生产中的错误。您的构建将使用新版本。如果幸运的话,这会破坏构建。如果你运气不好,它甚至可能会被忽视。
最后但同样重要的是,有些人喜欢使用 属性 值来声明 children 版本。强烈建议不要这样做,maven 会将其报告为警告。我个人从不这样做。原因还与构建的可重复性以及 Maven 假定发布构建永远不会改变的事实有关。让模块版本可以从外部调整并不是一个好主意。
编辑:
模块版本不一致的情况。
实际上这两种情况可以混合使用。
你可以有,例如:
Parent
---组件1
---组件2
---组件3
------Comp3Module1
------Como3模块2
------Comp3模块3
其中parent和三个组件版本不同,component3的三个模块共享相同的版本,如前所述。
问题 1)
在这种情况下,每个模块都有其独立指定的版本。
如前所述,使用 属性 指定模块版本是一种不好的做法,这就是我只能建议按字面指定版本的原因。
前面已经说过,要管理版本控制,最好的方法是使用发布插件,并将其与版本控制系统集成,例如 SVN。
其他答案详细介绍了如何使用它,所以我不会进一步详细说明,除非要求。
问题2)
推荐的方法与共享相同版本的情况相同,只是您需要多个属性。
parent 可以看起来像:
<properties>
<myproject.group>com.mycompany.myproject</myproject.group>
<component1.version>1.1.1-RC1</component1.version>
<component2.version>1.1.1-RC2</component2.version>
<component3.version>2.0.0</component3.version>
<properties>
然后你可以使用依赖管理来集中版本管理在parent。
例如,在 parent pom 中,
<dependencyManagement>
<dependencies>
<dependency>
<groupId>${myproject.group}</groupId>
<artifactId>component1</artifactId>
<version>${component1.version}</version>
</dependency>
<dependency>
<groupId>${myproject.group}</groupId>
<artifactId>component2</artifactId>
<version>${component2.version}</version>
<type>war</type>
</dependency>
<dependency>
<groupId>${myproject.group}</groupId>
<artifactId>comp3module1</artifactId>
<version>${component3.version}</version>
<type>ejb</type>
</dependency>
<dependency>
<groupId>${myproject.group}</groupId>
<artifactId>comp3module1</artifactId>
<version>${component3.version}</version>
<type>ejb-client</type>
</dependency>
<dependency>
<groupId>${myproject.group}</groupId>
<artifactId>comp3module2</artifactId>
<version>${component3.version}</version>
<type>war</version>
</dependency>
</dependencies>
</dependencyManagement>
现在,要从任何其他模块引用任何模块,很简单:
<dependency>
<groupId>${myproject.group}</groupId>
<artifactId>component1</artifactId>
</dependency>
<dependency>
<groupId>${myproject.group}</groupId>
<artifactId>comp3module1</artifactId>
<type>ejb-client</type>
</dependency>
版本是从 parent 自动管理的。您不需要在 children 依赖项中维护它们,这也变得不那么冗长。
如何更新子模块的版本?有很多像这样的 Whosebug 问题,但我找不到适合这种情况的问题...如果这是重复的,我会很高兴。
考虑以下项目。
parent
--mod1
--mod2
在开发发布周期开始时,我需要将父模块和模块更新到同一版本。如果父模块和模块的版本在整个发布过程中保持不变,那么我将只省略模块中的 <version>
标记并执行 versions:set -DnewVersion=1.1.1
以启动开发周期。但事实证明,这些模块并不是都以相同的版本结束循环。随着错误和修复的出现,只有那些有错误的模块才会得到更新。例如,parent 和 mod2 可能是版本 1.1.1-RC1,但 mod1 可能是 1.1.1-RC2。
因此我需要:
1) 在模块中包含一个 <version>
标签以独立跟踪每个模块版本。
2) 如果 mod2 需要 mod1 作为依赖项,我需要确保 mod2 引用最新版本的 mod1。
由此引出以下两个问题。
1) 在循环开始时,如何在一个 maven 命令中将父模块和模块设置为同一版本?我试过 version:set -DnewVersion=1.1.1
,但这只会更新所有 POM 的父版本,但不会更新模块的版本。我也试过 -N versions:update-child-modules
,但我认为我用错了,因为它什么都不做,只是显示所有模块都已跳过。
2) 这有点难,与上面的第 2 项匹配。如何一步更新 mod1 的版本和 mod2 对 mod1 版本的引用?我知道如何分两步完成:
父 pom:
<properties>
<!-- update this manually if mod1's version no longer matches parent -->
<mod1.version>${project.version}</mod1.version>
</properties>
mod2 pom:
<dependency>
<groupId>com.xxx</groupId>
<artifactId>mod1</artifactId>
<version>${mod1.version}</version>
</dependency>
当 mod1 升级到 1.1.1-RC2 时,我更新父 POM 和 mod1 POM 以反映这一点。这是两个步骤。无论如何把它变成一步?
我的例子很小,但在现实生活中有很多模块可以节省这个重要的时间,而且我很好奇。
1) 我过去也尝试过 version:set,但一直没能正常工作。它本应执行与 release:prepare 相同的过程,但实际上并非如此。所以你可以尝试的是mvn release:prepare -DautoVersionSubmodules -DdryRun
。这应该是在不检查任何内容到 repo 并且不制作任何标签的情况下进行所有更新。
2) 我相信 ClearTK 项目曾经遵循与您类似的策略:他们维护一个多模块项目,每个模块都有自己的发布周期。为了掌握情况,他们实施了一个自定义的 maven 插件来警告他们依赖版本不一致。
https://github.com/ClearTK/cleartk/tree/master/consistent-versions-plugin
虽然这样的插件不会进行您请求的更新,但它至少应该在需要更新时通知您。要真正解决您的问题,您可以考虑遵循与 ClearTK 相同的路线并实施您自己的 Maven 插件(或者您执行 ClearTK 最终完成的操作:切换到同步发布周期;))
好的,这就是我想到的。这是基于这篇 continuous-releasing-of-maven-artifacts 文章。
父 POM:
<properties>
<!-- versions of modules -->
<main.version>1.0</main.version>
<revision>SNAPSHOT</revision> <!-- default revision -->
<Module1.revision>${revision}</Module1.revision>
<Module2.revision>${revision}</Module2.revision>
<Module3.revision>${revision}</Module3.revision>
<Module4.revision>${revision}</Module4.revision>
<Module5.revision>${revision}</Module5.revision>
<Module1.version>${main.version}-${Module1.revision}</Module1.version>
<Module2.version>${main.version}-${Module2.revision}</Module2.version>
<Module3.version>${main.version}-${Module3.revision}</Module3.version>
<Module4.version>${main.version}-${Module4.revision}</Module4.version>
<Module5.version>${main.version}-${Module5.revision}</Module5.version>
</properties>
具有项目间依赖性的示例子 POM:
<groupId>com.xyz</groupId>
<artifactId>Module4</artifactId>
<packaging>jar</packaging>
<version>${Module4.version}</version>
<parent>
<groupId>com.xyz</groupId>
<artifactId>ParentProject</artifactId>
<version>1.0</version>
</parent>
<dependencies>
<dependency>
<groupId>com.xyz</groupId>
<artifactId>Module1</artifactId>
<version>${Module1.version}</version>
</dependency>
<dependency>
<groupId>com.xyz</groupId>
<artifactId>Module2</artifactId>
<version>${Module2.version}</version>
</dependency>
<dependency>
<groupId>com.xyz</groupId>
<artifactId>Module3</artifactId>
<version>${Module3.version}</version>
<type>jar</type>
</dependency>
<dependencies>
1) 在循环开始时,如何在一个 maven 命令中将父模块和模块设置为相同版本?
您不再需要。父 POM 可以保持相同的版本,只有在父 POM 更改时才会更改。在这种情况下,您可以使用 mvn version:set -DnewVersion=1.1.1
。但是您不需要使用这种方法。
相反,您可以使用 属性 main.version
动态设置版本。例如。 mvn clean deploy -Dmain.version=1.1.1
此外,要强制动态传递版本号,您可以省略我在上面的父 POM 中包含的默认值 main.version
属性。
2) 如何一步更新 mod1 的版本和 mod2 对 mod1 版本的引用?
这基本上归结为如何管理修订。如果我在 mvn 命令中不设置 revision
属性,那么所有模块将使用 SNAPSHOT
作为修订版。如果我将 revision
属性 设置为 RC1
那么所有模块都将获得该修订版。此外,如果我将 revision
设置为 RC1
,但将 Module4.revision
设置为 RC2
,则模块 4 获得 RC2,所有其他模块获得 RC1。这满足了客户对每个模块进行动态修订的要求。
这里有一些例子:
mvn clean deploy -Dmain.version=1.1.1
将所有模块设置为版本1.1.1-SNAPSHOT
。mvn clean deploy -Dmain.version=1.1.1 -Drevision=RC1
将所有模块设置为版本1.1.1-RC1
。mvn clean deploy -Dmain.version=1.1.1 -Drevision=RC1 -DModule4.revision=RC2
将所有模块设置为版本1.1.1-RC1
,除了 Module4 设置为版本1.1.1-RC2
.
有一个警告必须提及。如果将依赖模块(例如 Module1)的版本增加到 RC2,则还必须增加使用它的所有模块的版本,例如 Module4 也不能增加到 RC2(或下一个版本)。这是客户已经意识到的事情,也是我希望所有模块都具有相同版本的原因。但我真的很喜欢它的动态。基本上,现在通过命令行设置版本,无需更新 POM 文件。
1) 正如@rec 所说,maven 发布插件可以解决问题
$ mvn release:prepare -DautoVersionSubmodules=true
$ mvn release:perform
2) 您可以定义从 mod2 到 mod1 的依赖关系,例如:
<dependency>
<groupId>com.xxx</groupId>
<artifactId>mod1</artifactId>
<version>LATEST</version>
</dependency>
更多信息:How do I tell Maven to use the latest version of a dependency?
我测试了这两种解决方案并且有效!希望对你有帮助:)
问题 1)
管理应用程序生命周期和发布的最佳方式是使用发布插件。
您可能知道,Maven 的哲学是约定优于配置。 Maven 惯例是在开发期间使用快照版本(以 -SNAPSHOT 结尾的版本)并仅为发布分配非快照版本。
假设您正在开发 1.1.1 版。在开发过程中,您只需使用 1.1.1-SNAPSHOT。 Maven 将负责快照的更新。如果使用工件存储库,您可以使用 -U 来确保您始终拥有最新版本的快照。
发布准备就绪后,发布插件会生成并部署版本 1.1.1,并使用新的开发版本更新 POM,例如 1.1.2-SNAPSHOT。
关于多模块项目,有两种情况:模块相关但独立(例如多个Web应用程序)或者它们是单个大型应用程序或库的模块并且它们共享版本。你似乎对后者感兴趣。
在这种情况下最好的方法就是继承相同的 parent(也可能是 root)模块,包括它的版本。您引用 parent group:artifact:version 并且没有指定 children 的版本。通常你也继承组,所以你的 child pom 可以看起来像:
<parent>
<groupId>com.mycompany.myproject</groupId>
<artifactId>myproject-parent</artifactId>
<version>1.1.1-SNAPSHOT</version>
<relativePath>../myproject-parent</relativePath>
</parent>
<artifactId>myproject-module1</artifactId>
现在您只需要在发布插件的帮助下处理 children 指向 parent 的正确版本。
为了帮助它了解 children,您应该通过包含模块部分使您的 parent pom 也成为根 pom,如下所示。
问题2) 我通常在 parent 中声明属性,其中包含可能引用的所有工件的所有版本。如果几个模块共享版本,你只需要一个属性。 parent 可以看起来像:
<groupId>com.mycompany.myproject</groupId>
<artifactId>myproject-parent</artifactId>
<version>1.1.1-SNAPSHOT</version>
<packaging>pom</packaging>
<properties>
<myproject.version>1.1.1-SNAPSHOT</myproject.version>
</properties>
.......
<modules>
<module>../myproject-module1</module>
...
</modules>
Children可以使用
引用其他模块<version>${myproject.version}</version>
使用 LATEST 声明依赖项是一种非常糟糕的做法。假设您为版本 1.1.1 执行此操作。现在您正在使用 1.1.2-SNAPSHOT 版本,并且您可能在本地存储库中安装了此版本的工件。
现在说由于某种原因您需要重建版本 1.1.1,例如因为生产中的错误。您的构建将使用新版本。如果幸运的话,这会破坏构建。如果你运气不好,它甚至可能会被忽视。
最后但同样重要的是,有些人喜欢使用 属性 值来声明 children 版本。强烈建议不要这样做,maven 会将其报告为警告。我个人从不这样做。原因还与构建的可重复性以及 Maven 假定发布构建永远不会改变的事实有关。让模块版本可以从外部调整并不是一个好主意。
编辑:
模块版本不一致的情况。
实际上这两种情况可以混合使用。 你可以有,例如:
Parent
---组件1
---组件2
---组件3
------Comp3Module1
------Como3模块2
------Comp3模块3
其中parent和三个组件版本不同,component3的三个模块共享相同的版本,如前所述。
问题 1) 在这种情况下,每个模块都有其独立指定的版本。 如前所述,使用 属性 指定模块版本是一种不好的做法,这就是我只能建议按字面指定版本的原因。 前面已经说过,要管理版本控制,最好的方法是使用发布插件,并将其与版本控制系统集成,例如 SVN。 其他答案详细介绍了如何使用它,所以我不会进一步详细说明,除非要求。
问题2) 推荐的方法与共享相同版本的情况相同,只是您需要多个属性。 parent 可以看起来像:
<properties>
<myproject.group>com.mycompany.myproject</myproject.group>
<component1.version>1.1.1-RC1</component1.version>
<component2.version>1.1.1-RC2</component2.version>
<component3.version>2.0.0</component3.version>
<properties>
然后你可以使用依赖管理来集中版本管理在parent。
例如,在 parent pom 中,
<dependencyManagement>
<dependencies>
<dependency>
<groupId>${myproject.group}</groupId>
<artifactId>component1</artifactId>
<version>${component1.version}</version>
</dependency>
<dependency>
<groupId>${myproject.group}</groupId>
<artifactId>component2</artifactId>
<version>${component2.version}</version>
<type>war</type>
</dependency>
<dependency>
<groupId>${myproject.group}</groupId>
<artifactId>comp3module1</artifactId>
<version>${component3.version}</version>
<type>ejb</type>
</dependency>
<dependency>
<groupId>${myproject.group}</groupId>
<artifactId>comp3module1</artifactId>
<version>${component3.version}</version>
<type>ejb-client</type>
</dependency>
<dependency>
<groupId>${myproject.group}</groupId>
<artifactId>comp3module2</artifactId>
<version>${component3.version}</version>
<type>war</version>
</dependency>
</dependencies>
</dependencyManagement>
现在,要从任何其他模块引用任何模块,很简单:
<dependency>
<groupId>${myproject.group}</groupId>
<artifactId>component1</artifactId>
</dependency>
<dependency>
<groupId>${myproject.group}</groupId>
<artifactId>comp3module1</artifactId>
<type>ejb-client</type>
</dependency>
版本是从 parent 自动管理的。您不需要在 children 依赖项中维护它们,这也变得不那么冗长。