67

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

目前,我们不会为我们的项目增加版本号,并且所有内容都已在版本0.0.1-SNAPSHOT中放置了一年多。我想知道为 Web 应用程序进行持续交付的 Maven 方式是什么。在每次提交时提高版本号似乎有点矫枉过正,而且永远不会像我们现在所做的那样提高版本号,这似乎也是错误的。

对于这种类型的 Maven 使用,推荐的最佳实践是什么?

这个问题实际上是两个方面的:

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

7 回答 7

51

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

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

于 2013-08-27T19:04:54.420 回答
42

这是我基于 Mark O'Connor 的回答链接的视频的总结。

  • 该解决方案需要像 git 这样的 DVCS 和像 Jenkins 这样的 CI 服务器。
  • 不要在持续交付管道中使用快照构建,也不要使用 maven 发布插件。
  • 快照版本例如1.0-SNAPSHOT变成了真实版本,例如1.0.buildNumberJenkinsbuildNumber工作编号。

算法步骤:

  1. Jenkins用源码克隆了git repo,说源码有版本1.0-SNAPSHOT
  2. Jenkins 创建了一个名为的 git 分支1.0.JENKINS-JOB-NUMBER,以便将快照版本转换为真实版本1.0.124
  3. Jenkins 调用 maven 版本插件将 pom.xml 文件中的版本号从1.0-SNAPSHOT更改为1.0.JENKINS-JOB-NUMBER
  4. 詹金斯调用mvn install
  5. 如果mvn install成功,那么 Jenkins 将提交分支1.0.JENKINS-JOB-NUMBER,并在 git 中使用适当的标签创建一个真正的非快照版本,以便稍后重现。如果mvn install失败,那么 Jenkins 只会删除新创建的分支并使构建失败。

我强烈推荐从马克的回答链接的视频。

于 2013-10-06T14:05:31.137 回答
24

从 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}.

您可以使用例如https://wiki.jenkins-ci.org/display/JENKINS/Version+Number+Plugin来生成有趣的内部版本号。

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

于 2016-12-22T12:55:04.807 回答
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

版本,但在构建新版本时,构建服务器可以用更独特和可追溯的东西替换 SNAPSHOT。

例如其中之一:

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

因此,主要和次要数字可以用于营销问题,或者只是表明达到了一个新的重要里程碑,并且可以在您需要时手动更改。buildNumber(来自您的持续集成服务器的编号)或 scmNumber(Subversion 或 GIT 的修订版)使每个版本都独一无二且可追溯。使用 buildNumber 或 Subversion 修订版时,项目版本甚至是可排序的(不使用 GIT 编号)。使用 buildNumber 或 scmNumber 也很容易查看此版本中的更改。

另一个例子是stackoverflow的版本控制,它使用

<year>.<month>.<day>.<buildNumber>

这里缺少的链接:

于 2013-08-27T06:12:34.530 回答
7

不要这样做!

<Major>.<minor>-<build>

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

这很糟糕,就好像你在 maven 中要求最新版本的东西一样,那么上面的观点就赢了。

解决方案是在内部版本号之前使用小数点而不是连字符。

做这个!

<Major>.<minor>.<build>

本地有 SNAPSHOT 版本是可以的,但作为构建的一部分,最好使用

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

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

一群开发人员在同一个major.minor 版本上发布是可以的——但要注意小的变化是非破坏性的,主要版本的变化有一些破坏性的API 变化,或者功能/行为的弃用。

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

于 2014-03-29T21:05:32.053 回答
2

作为起点,您可以看看Maven: The Complete Reference。项目版本。

然后有一篇关于版本控制策略的好帖子。

于 2013-08-27T03:18:44.843 回答
1

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

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

示例:247-262e37b9。

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

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

于 2015-02-28T00:03:26.353 回答