在进行持续交付时,自动项目版本的Maven方式是什么?

时间:2013-08-27 02:43:26

标签: java maven continuous-integration maven-3 continuous-delivery

我有一个Web应用程序,我们可以在功能准备就绪时部署到生产环境,有时一天可能会发生几次,有时可能会在发布之间的几周内部署。

目前,我们不会增加项目的版本号,而且所有版本都在0.0.1-SNAPSHOT版本上保存了一年多。 我想知道为Web应用程序进行持续交付的Maven方式是什么。在每次提交时提高版本号并且从不像我们现在所做的那样碰撞版本号似乎有点过分,似乎也是错误的。

此类Maven使用的推荐最佳做法是什么?

问题实际上是双重问题:

  • 在单个pom.xml文件中推进项目版本号(可能有很多)。
  • 更新所有相关组件中的版本号,以使用彼此的最新版本号。

7 个答案:

答案 0 :(得分:41)

我建议以下演示文稿讨论使用Maven进行持续交付的实际情况:

关键点是每个版本都是潜在版本,所以不要使用快照。

答案 1 :(得分:34)

这是我根据Mark O'Connor的回答链接的视频摘要。

  • 解决方案需要像git这样的DVCS和像Jenkins这样的CI服务器。
  • 不要在Continuous Delivery管道中使用快照构建,也不要使用maven release插件。
  • 1.0-SNAPSHOT等快照版本将转换为1.0.buildNumber等真实版本,其中buildNumber是Jenkins作业编号。

算法步骤:

  1. Jenkins使用源代码克隆git repo,并说源代码的版本为1.0-SNAPSHOT
  2. Jenkins创建了一个名为1.0.JENKINS-JOB-NUMBER的git分支,因此快照版本变为真实版本1.0.124
  3. Jenkins调用maven版本插件将pom.xml文件中的版本号从1.0-SNAPSHOT更改为1.0.JENKINS-JOB-NUMBER
  4. Jenkins调用mvn install
  5. 如果mvn install成功,那么Jenkins将提交分支1.0.JENKINS-JOB-NUMBER,并在git中使用适当的标记创建真正的非快照版本以便稍后再现。如果mvn install失败,那么Jenkins将删除新创建的分支并使构建失败。
  6. 我强烈推荐Mark的答案链接的视频。

答案 2 :(得分:14)

从Maven 3.2.1开始,支持开箱即用的交付友好版本:https://issues.apache.org/jira/browse/MNG-5576 您可以在版本中使用3个预定义变量:

${changelist}
${revision}
${sha1}

所以你基本上做的是:

  1. 将您的版本设置为例如1.0.0-${revision}。 (您可以使用mvn versions:set在多模块项目中快速正确地执行此操作。)
  2. 将一个属性<revision>SNAPSHOT</revision>用于本地开发。
  3. 在您的CI环境中,运行mvn clean install -Drevision=${BUILD_NUMBER}或类似内容,甚至mvn clean verify -Drevision=${BUILD_NUMBER}
  4. 您可以使用例如https://wiki.jenkins-ci.org/display/JENKINS/Version+Number+Plugin来生成有趣的内部版本号。

    一旦发现构建稳定(例如通过验收测试),您就可以将版本推送到Nexus或其他存储库。任何不稳定的构建都会变成垃圾。

答案 3 :(得分:9)

有一些很好的讨论和建议如何处理maven版本号和持续传递(CD)(我将在我的部分答案后添加它们。)

首先我对SNAPSHOT版本的看法。在maven中,SNAPSHOT显示当前正在开发到SNAPSHOT后缀之前的特定版本。因此,像Nexus或maven-release-plugin这样的工具对SNAPSHOTS有特殊的处理方式。对于Nexus,它们存储在一个单独的存储库中,并允许使用相同的SNAPSHOT版本更新多个人工制品。所以SNAPSHOT可以在你不知道的情况下改变(因为你永远不会增加你的pom中的任何数字)。因此,我不建议在项目中使用SNAPSHOT依赖项,特别是在CD世界中,因为构建不再可靠。

由于上述原因,当您的项目被其他项目使用时,SNAPSHOT作为项目版本会出现问题。

对我而言,SNAPSHOT的另一个问题是不再可追溯或可重现。当我在生产中看到版本0.0.1-SNAPSHOT时,我需要进行一些搜索以找出它是从构建的修订版本构建的。当我在文件系统上发现这个软件的版本时,我需要查看pom.properties或MANIFEST文件,看看这是旧垃圾还是最新版本。

为避免手动更改版本号(特别是当您每天构建多个版本时),让构建服务器为您更改编号。所以对于开发我会选择

<major>.<minor>-SNAPSHOT

版本但是在构建新版本时,Build Server可以用更独特和可追踪的东西替换SNAPSHOT。

例如其中一个:

<major>.<minor>-b<buildNumber>
<major>.<minor>-r<scmNumber>

因此,主要和次要号码可用于营销问题,或仅显示达到新的重要里程碑,并且可以在您需要时手动更改。 buildNumber(来自Continuous Integration服务器的编号)或scmNumber(SUbversion或GIT的修订版)使每个版本都是唯一且可追踪的。使用buildNumber或Subversion修订时,项目版本甚至可以排序(不使用GIT编号)。使用buildNumber或scmNumber也很容易看出此版本中有哪些更改。

另一个例子是使用

的stackoverflow的版本控制
<year>.<month>.<day>.<buildNumber>

这里缺少链接:

答案 4 :(得分:6)

不要这样做!

<Major>.<minor>-<build>

会在后面咬你,因为Maven在连字符之后将任何东西视为LEXICAL。这意味着版本1将在词法上高于10。

这很糟糕,好像你在maven中要求提供最新版本的内容,然后上述观点获胜。

解决方案是使用小数点而不是构建号前面的连字符。

DO DOIS!

<Major>.<minor>.<build>

在本地拥有SNAPSHOT版本是可以的,但作为构建的一部分,使用它会更好

mvn versions:set -DnewVersion=${major}.${minor}.${build.number}

有一些方法可以从pom中派生主要/次要版本,例如使用help:在调用版本之前,计算并管道到环境变量:set。这很脏,但我真的摸不着头脑(以及我团队中的其他人)让它变得更简单,而且(当时)Maven还不够成熟来处理这个问题。我相信Maven 2.3.1可能会有一些帮助这个的东西,所以这些信息可能不再相关。

一群开发人员可以在相同的major.minor版本上发布 - 但是要注意微小的更改是不会破坏的,并且主要的版本更改会有一些破坏的API,这总是很好的更改或弃用功能/行为。

从持续交付的角度来看,每个构建都可能可释放,因此每次签入都应该创建构建。

答案 5 :(得分:2)

作为起点,您可以查看Maven: The Complete Reference. Project Versions.

然后有一个很好的post on versioning strategy.

答案 6 :(得分:1)

在我的网络应用程序工作中,我们目前使用此版本控制模式:

<jenkins build num>-<git-short-hash>

示例:247-262e37b9。

这很好,因为它为您提供了一个始终唯一且可追溯到生成它的jenkins构建和git修订版本的版本。

在Maven 3.2.1+中,他们最终杀死了使用$ {property}作为版本的警告,这样就可以很容易地构建它们。只需更改所有pom即可使用<version>${revision}</version>并使用-Drevision=whatever进行构建。唯一的问题是,在你发布的poms中,版本将保留在${revision}的实际pom文件中,这可能会导致各种奇怪的问题。为了解决这个问题,我写了一个简单的maven插件(https://github.com/jeffskj/cd-versions-maven-plugin),它在文件中替换变量。