Maven部署只更改已修改的构件

12

我正在使用带有Nexus 1.4.0的Maven 2.2。

假设我有这样一个POM结构(带有相应的版本):

parentproj, v1.0.1
 - childproj1, v1.0.2
 - childproj2, v1.0.7

childproj1和childproj2代表应用程序的不同部分(例如GUI和后端),我希望能够使它们的版本保持独立,以便我可以发布后端的新版本而无需发布GUI的新版本。

现在,要将这个结构部署到Nexus,去parentproj并运行下面的命令会很方便:

  

mvn deploy -DperformRelease=true

这将把所有构件部署到Nexus的release存储库中。第一次部署时这样做没有问题,但第二次就会遇到问题:假设我更新了childproj1,这样我们现在有以下版本:

parentproj, v1.0.1
 - childproj1, v1.0.3
 - childproj2, v1.0.7
在这种情况下,Nexus将不允许我从parentproj执行mvn deploy操作,因为它已经有childproj2的1.0.7版本的副本。Nexus会说“资源,非法请求:ID='releases'的仓库不允许更新工件。”这没关系,我不想因错误而更新现有的版本。
但我想做的是告诉Maven类似于“仅部署那些版本不存在于发布存储库中的工件”,可能有办法实现吗?还是我必须单独部署每个项目?
5个回答

4
根据我的经验,将所有组件部署并使用相同的版本号通常更容易。例如,如果我的团队正在开发版本1.0.7,则所有子模块的版本号都是1.0.7-SNAPSHOT,即使某些模块中没有代码发生变化,在发布之前也是如此。然后在部署时,我们会部署整个应用程序。我认为它比分批部署有几个优点。首先,如果您需要回滚到上一个稳定版本,您只需回滚到所有模块的1.0.6版本-您不必记住后端是1.0.3而GUI是1.0.6。其次,它确保所有组件正确编译并针对彼此进行了测试,作为一个逻辑组。抱歉,我知道这不是您问题的具体答案,但至少对于我的团队来说,稍微有所思考是有益的。

1
谢谢你的回答,约翰。我们也在调查这种方法,很可能最终采取这种方法。我同意版本一致性带来了很多价值,但我也担心对于一个大型项目,如果你必须为任何更改升级整个平台,构建过程可能会变得太臃肿和耗时。 - David
建议在版本号上使用SNAPSHOT限定符来解决这个问题,使用正确的方式和正确的用法。 - whaley
我不同意最后一句话关于编译在一起和一起测试的说法。如果您在JAR上有固定版本依赖关系,Maven将使用这些JAR编译您的项目,因此您仍将获得与SNAPSHOT或固定版本依赖关系一起编译的所有内容。至于测试,对于真正的单元测试,我认为类依赖关系,特别是跨JAR边界的依赖关系,应该被模拟。这意味着除非您有某种功能/集成测试运行到已部署的应用程序中,否则您的代码永远不会一起测试,然后SNAPSHOT或固定版本就不再重要了。 - Jesse Webb

3
首先,我认为你应该区分父项目和聚合项目。父项目应该用于那些多个项目共有的设置,例如依赖版本;聚合项目应该用于同时构建一组项目,例如一组jar包和包含它们的war文件。
这两种类型的项目最好保持分离。父项目通常不会经常更改,当它需要更改时,通常最好发布所有依赖它的项目的新版本;聚合项目的唯一目的是驱动一堆项目的构建,因此它的发布版本号可能需要在其中包含的任何项目需要发布时更改。
一旦你将父项目与聚合器分离开来,你就可以更好地选择是否遵循John Paulett的建议并将所有内容都保持在相同的版本号,还是只在实际需要发布每个项目时才尝试更改其版本号。第一个选项更简单,也更少出错,但会导致您发布未更改的库的新版本。如果例如您需要发布补丁而不是完整版本,则可能不可接受。第二个选项更复杂、容易出错,但会导致您的发布版本号与软件的演变相匹配。Maven发布插件和Jenkins持续集成工具可能会对此有所帮助,我认为你应该检查一下它们。另外,请看看是否可以将Maven升级至至少2.2.1版本,并将Nexus升级至更高版本。

+1 是区分父 POM 和聚合 POM 的,有关其区别的更多细节,请阅读 POM 继承和聚合:http://maven.apache.org/guides/introduction/introduction-to-the-pom.html。 - Jesse Webb

2
我建议您使用Artifact Exists Maven Plugin (https://github.com/chonton/exists-maven-plugin)。这个神奇的东西只需要在parent.pom中提及,就会自动跳过所有已经存在于仓库(Nexus或Artifactory)中的发布构件的安装和部署阶段,并且仍然可以部署快照版本(可配置)。
示例:
  <plugin>
    <groupId>org.honton.chas</groupId>
    <artifactId>exists-maven-plugin</artifactId>
    <version>0.0.6</version>
    <executions>
      <execution>
        <goals>
          <goal>remote</goal>
        </goals>
      </execution>
    </executions>
  </plugin>

</plugins>


1

如果您计划独立维护、构建和部署模块,我建议您考虑为每个模块设置单独的CI和mvn deploy作业。具有独立的mvn deploy作业将使您在开箱即用时获得所需的行为。这意味着不使用聚合器pom(parentprj)尝试构建和部署这些模块。

如果您想从聚合器pom执行所有操作,例如构建和部署,那么我建议您遵循John的答案并保持所有版本号同步。

这取决于您的团队希望如何查看代码库。如果您想以真正的模块化方式保持事物,您应该像积木一样使用您的Maven模块,以不同的方式处理它们,直到您准备好将整个应用程序组合在一起。如果您的应用程序具有更多的单块性质,请将其视为如此并保持同步。这并不意味着您仍然不能分离出单独的Maven模块来维护代码库的模块化,只是认识到它们在您更大的应用程序上下文之外没有任何价值。

一个做出这个决定的好方法是问自己“是否有其他项目/应用需要引用此模块作为依赖项?”。如果是,最佳实践是独立地构建、版本化和部署它。如果没有,我认为匹配版本没有任何问题。

1

显然,Maven、Nexus或Archiva都没有解决这个需求。目前,只能通过构建管理器设置的额外技巧来解决,就像之前的帖子中所建议的那样。

在理想的世界里

  • pom文件应该包括:

    • 模块的发布版本和快照版本
    • 文件定义,如果更改了这些文件,就需要使用快照版本
    • 发布模块的源代码管理系统引用
  • 依赖模块的pom文件应该在适当的依赖项部分添加发布版本信息和快照版本信息,以便如果存储库中存在快照库,则链接到快照库,否则链接到发布库

  • Maven反应堆应该有一个选项来读取依赖关系和文件更改信息(SCM diff),以知道是否要使用给定模块的发布版本或快照版本。

  • 默认情况下,发布插件应该跳过仍然可以使用其发布版本的模块的发布。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接