maven 仅部署更改的工件

Posted

技术标签:

【中文标题】maven 仅部署更改的工件【英文标题】:maven deploy changed artifacts only 【发布时间】:2010-12-24 00:52:18 【问题描述】:

我正在使用 maven 2.2 和 nexus 1.4.0

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

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

childproj1 和 childproj2 代表应用程序的不同部分(例如 gui 和后端),我希望能够将它们的版本分开,以便我可以发布新版本的后端而不必发布新版本的 gui .

现在,要将这个结构部署到 Nexus,去 parentproj 说会很方便

mvn deploy -DperformRelease=true

这会将所有工件部署到 Nexus realease 存储库。这在我第一次部署时运行良好,但第二次遇到问题:假设我对 childproj1 进行了更新,因此我们现在拥有以下版本:

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

在这种情况下,Nexus 不会让我从 parentproj 执行 mvn deploy,因为它在 1.0.7 版本中已经有 childproj2 的副本。 Nexus 会说“资源,非法请求:ID='releases' 的存储库不允许更新工件。”这很好,我不想错误地更新现有版本。

但我想我想做的是能够告诉 maven 类似“仅部署那些版本尚未出现在发布存储库中的工件”。

有没有办法做到这一点,还是我必须自己部署每个项目?

【问题讨论】:

【参考方案1】:

根据我的经验,部署所有内容更容易,并且通常对所有组件使用相同的版本号。例如,如果我的团队正在开发版本 1.0.7,所有子模块的版本号都是 1.0.7-SNAPSHOT,直到我们发布,即使某些模块中没有代码更改。然后,当我们部署时,我们将部署整个应用程序。我认为与零散部署相比,它有几个优点。首先,如果您每个人都必须回滚到上一个稳定版本,您只需将所有模块回滚到 1.0.6——您不必记住后端是 1.0.3 而 GUI 是 1.0.6。其次,它确保所有组件都相互正确编译,并作为一个逻辑组进行了测试。

抱歉,我知道这不是对您问题的具体答案,但是,至少在我的团队的情况下,稍微不同的想法很有用

【讨论】:

感谢您回答约翰,我们也在调查这种方法,它很可能是最终采用的方法。我同意版本一致性带来了很多价值,但我也担心对于大型项目,如果您必须升级整个平台以进行任何更改,构建过程可能会变得过于臃肿和耗时。 +1 建议在版本上(正确和正确)使用 SNAPSHOT 限定符来解决此问题。 我不同意最后关于一起编译和测试的说法。如果您对 JAR 有固定版本依赖项,Maven 将使用这些 JAR 编译您的项目,因此您仍然可以将所有内容与 SNAPSHOT 或固定版本依赖项一起编译。至于测试,对于真正的单元测试,我认为应该模拟类依赖,尤其是 JAR 边界上的依赖。这意味着您的代码永远不会一起测试,除非您对已部署的应用程序运行某种功能/集成测试,然后 SNAPSHOT 或固定版本就不再重要了。【参考方案2】:

我建议,如果您计划独立维护、构建和部署模块,您应该考虑为每个模块设置单独的 CI 和 mvn deploy 作业。拥有独立的mvn deploy 工作将为您提供您正在寻找的开箱即用的行为。这意味着不要使用聚合器 pom (parentprj) 来尝试构建和部署这些模块。

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

这仅取决于您的团队希望如何看待代码库。如果你想以真正的模块化方式保持东西,你应该像构建块一样使用你的 maven 模块,以不同的方式对待它们,直到你准备好将整个应用程序放在一起。如果您的应用程序本质上更加单一,请按此处理并保持同步。这并不意味着您仍然不能拆分单独的 maven 模块来维护基于代码的模块化,只要认识到它们在您的大型应用程序的上下文之外没有任何价值。

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

【讨论】:

【参考方案3】:

首先,我认为你应该区分父项目和聚合项目。父项目应该用于多个项目共有的设置,例如依赖的版本;应该使用聚合项目以便同时构建一组项目,例如一组罐子和包含它们的战争。

这两种项目最好分开。父项目通常不会经常更改,当它发生变化时,通常最好发布所有依赖它的项目的新版本;聚合项目的唯一目的是推动一堆项目的构建,因此它的发布号可能会在它包含的一个项目需要发布时更改。

将父级与聚合器分离后,您可以更好地选择是遵循 John Paulett 的建议并将所有内容保持在相同的版本号,还是仅在您真正需要发布时尝试更改每个项目的版本号它。第一个选项更简单且不易出错,但会导致您发布未更改的新版本库。例如,如果您需要发布补丁而不是完整版本,这可能是不可接受的。第二个选项更复杂且容易出错,但会导致您的版本号与软件的发展相匹配。 Maven 发布插件和 Jenkins 持续集成工具可能会有所帮助,我认为您应该检查一下。另外,看看您是否可以将 Maven 升级到至少 2.2.1 版和 Nexus 到更新的版本。

【讨论】:

+1 用于区分父级和聚合器 POM。有关差异的更多详细信息,请阅读 POM 继承和聚合:maven.apache.org/guides/introduction/…【参考方案4】:

显然,maven 没有解决这个需求,Nexus 或档案也没有。 目前,它只能通过构建管理器设置的额外技巧来解决,就像以前的帖子中建议的那样。

在一个理想的世界里

pom 将包括 .模块的发布版本和快照版本 .文件的定义,如果更改,则证明使用快照版本是合理的 .已发布模块的源代码控制管理系统参考

依赖模块 poms 将在适当的依赖部分中添加快照版本信息旁边的发布版本信息,以便它链接到快照库(如果存在于 repo 中),否则链接到发布库

maven reactor 可以选择读取依赖层次结构和文件更改信息 (scm diff),以了解给定模块是在其发布版本还是快照版本中使用。

默认情况下,发布插件会跳过模块的发布,但仍然可以根据文件更改和依赖信息与其发布版本一起使用。

【讨论】:

【参考方案5】:

我建议您使用 Artifact Exists Maven 插件 (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>

【讨论】:

以上是关于maven 仅部署更改的工件的主要内容,如果未能解决你的问题,请参考以下文章

根据配置文件更改部署的工件名称

从 nexus 获取最新的构建工件

如何构建仅签入代码文件以及如何仅签入该构建的 tfs 中的代码工件?

更改 Jenkins 构建工件文件所有权

IntelliJ IDEA:Maven,项目编译和部署

Maven 发布插件:如何在发布时仅部署分发 jar:执行