Java 做持续交付时自动项目版本的Maven方式是什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18456111/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 01:46:17  来源:igfitidea点击:

What is the Maven way for automatic project versions when doing continuous delivery?

javamavencontinuous-integrationmaven-3continuous-delivery

提问by ams

I have a web application where we deploy to production whenever a feature is ready, sometimes that can be a couple of times a day, sometimes it can be a couple of weeks between releases.

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

Currently, we don't increment our version numbers for our project, and everything has been sitting at version 0.0.1-SNAPSHOTfor well over a year. I am wondering what is the Maven way for doing continuous delivery for a web apps. It seems overkill to bump up the version number on every commit, and never bumping the version number like we are doing now, also seems wrong.

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

What is the recommend best practice for this type of Maven usage?

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

The problem is actually a two-fold one:

问题实际上有两个方面:

  • Advancing project version number in individual pom.xmlfile (and there can be many).
  • Updating version number in all dependent components to use latest ones of each other.
  • 提高单个pom.xml文件中的项目版本号(可以有很多)。
  • 更新所有相关组件中的版本号以使用彼此的最新版本。

采纳答案by Mark O'Connor

I recommend the following presentation that discusses the practical realities of doing continuous delivery with Maven:

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

The key takeaway is each build is a potential release, so don't use snapshots.

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

回答by dmitri

As a starting point you may have a look at Maven: The Complete Reference. Project Versions.

作为起点,您可以查看Maven:完整参考。项目版本。

Then there is a good post on versioning strategy.

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

回答by mszalbach

There are some great discussions and proposals how to deal with the maven version number and continuous delivery (CD) (I will add them after my part of the answer).

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

So first my opinion on SNAPSHOT versions. In maven a SNAPSHOT shows that this is currently under development to the specific version before the SNAPSHOT suffix. Because of this, tools like Nexus or the maven-release-plugin has a special treatment for SNAPSHOTS. For Nexus they are stored in a separate repository and its allowed to update multiple artefacts with the same SNAPSHOT release version. So a SNAPSHOT can change without you knowing about it (because you never increment any number in your pom). Because of this I do not recommend to use SNAPSHOT dependencies in a project especially in a CD world since the build is not reliable any more.

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

SNAPSHOT as project version would be a problem when your project is used by other ones, because of the above reasons.

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

An other problem of SNAPSHOT for me is that is not really traceable or reproducibly any more. When I see a version 0.0.1-SNAPSHOT in production I need to do some searching to find out when it was build from which revision it was build. When I find a releases of this software on a filesystem I need to have a look at the pom.properties or MANIFEST file to see if this is old garbage or maybe the latest and greatest version.

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

To avoid the manual change of the version number (especially when you build multiple builds a day) let the Build Server change the number for you. So for development I would go with a

为避免手动更改版本号(尤其是当您一天构建多个构建时),让构建服务器为您更改版本号。所以为了发展,我会去

<major>.<minor>-SNAPSHOT

version but when building a new release the Build Server could replace the SNAPSHOT with something more unique and traceable.

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

For example one of this:

例如其中之一:

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

So the major and minor number can be used for marketing issues or to just show that a new great milestone is reached and can be changed manually when ever you want it. And the buildNumber (number from your Continuous Integration server) or the scmNumber (Revision of SUbversion or GIT) make each release unique and traceable. When using the buildNumber or Subversion revision the project versions are even sortable (not with GIT numbers). With the buildNumber or the scmNumber is also kinda easy to see what changes are in this release.

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

An other example is the versioning of stackoverflow which use

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

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

And here the missing links:

这里缺少的链接:

回答by ams

This is my summary based on the video linked by Mark O'Connor's answer.

这是我根据 Mark O'Connor 的回答链接的视频所做的总结。

  • The solution requires a DVCS like git and a CI server like Jenkins.
  • Don't use snapshot builds in the Continuous Delivery pipeline and don't use the maven release plugin.
  • Snapshot versions such as 1.0-SNAPSHOTare turned into real versions such as 1.0.buildNumberwhere the buildNumberis the Jenkins job number.
  • 该解决方案需要像 git 这样的 DVCS 和像 Jenkins 这样的 CI 服务器。
  • 不要在持续交付管道中使用快照构建,也不要使用 maven 发布插件。
  • 快照版本,如1.0-SNAPSHOT都变成了现实版本,如1.0.buildNumberbuildNumber是詹金斯作业号。

Algorithm steps:

算法步骤:

  1. Jenkins clones the git repo with the source code, and say the source code has version 1.0-SNAPSHOT
  2. Jenkins creates a git branch called 1.0.JENKINS-JOB-NUMBERso the snapshot version is turned into a real version 1.0.124
  3. Jenkins invokes the maven versions plugin to change the version number in the pom.xml files from 1.0-SNAPSHOTto 1.0.JENKINS-JOB-NUMBER
  4. Jenkins invokes mvn install
  5. If the mvn installis a success then Jenkins will commit the branch 1.0.JENKINS-JOB-NUMBERand a real non-snapshot version is created with a proper tag in git to reproduce later. If the mvn installfails then Jenkins will just delete the newly created branch and fail the build.
  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 将删除新创建的分支并使构建失败。

I highly recommend the video linked from Mark's answer.

我强烈推荐从 Mark 的回答中链接的视频。

回答by user924272

DON'T DO THIS!

不要这样做!

<Major>.<minor>-<build>

will bite you in the backside because Maven treats anything after a hyphen as LEXICAL. This means version 1 will be lexically higher than 10.

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

This is bad as if you're asking for the latest version of something in maven, then the above point wins.

这很糟糕,就好像您在 maven 中要求最新版本的东西一样,那么以上一点就获胜了。

The solution is to use a decimal point instead of a hyphen preceding the build number.

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

DO THIS!

做这个!

<Major>.<minor>.<build>

It's okay to have SNAPSHOT versions locally, but as part of a build, it's better to use

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

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

There are ways to derive the major/minor version from the pom, eg using help:evaluate and pipe to a environment variable before invoking versions:set. This is dirty, but I really scratched my head (and others in my team) to make it simpler, and (at the time) Maven wasn't mature enough to handle this. I believe Maven 2.3.1 might have something that go some way in helping this, so this info may no longer be relevant.

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

It's okay for a bunch of developers to release on the same major.minor version - but it's always good to be mindful that minor changes are non-breaking and major version changes have some breaking API change, or deprecation of functionality/behaviour.

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

From a Continuous Delivery perspective every build is potentiallyreleasable, therefore every check-in should create a build.

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

回答by Jeff S

At my work for web apps we currently use this versioning pattern:

在我为 Web 应用程序工作时,我们目前使用这种版本控制模式:

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

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

Example: 247-262e37b9.

示例:247-262e37b9。

This is nice because it it gives you a version that is always unique and traceable back to the jenkins build and git revision that produced it.

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

In Maven 3.2.1+ they finally killed the warnings for using a ${property} as a version so that makes it really easy to build these. Simply change all your poms to use <version>${revision}</version>and build with -Drevision=whatever. The only issue with that is that in your released poms the version will stay at ${revision}in the actual pom file which can cause all sorts of weird issues. To solve this I wrote a simple maven plugin (https://github.com/jeffskj/cd-versions-maven-plugin) which does the variable replacement in the file.

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

回答by Piotr Gwiazda

Starting from Maven 3.2.1 continuous delivery friendly versions are supported out of the box : https://issues.apache.org/jira/browse/MNG-5576You can use 3 predefined variables in version:

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

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

So what you basically do is :

所以你基本上做的是:

  1. Set your version to e.g. 1.0.0-${revision}. (You can use mvn versions:setto do it quickly and correctly in multi-module project.)
  2. Put a property <revision>SNAPSHOT</revision>for local development.
  3. In your CI environment run mvn clean install -Drevision=${BUILD_NUMBER}or something like this or even mvn clean verify -Drevision=${BUILD_NUMBER}.
  1. 将您的版本设置为 eg 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}.

You can use for example https://wiki.jenkins-ci.org/display/JENKINS/Version+Number+Pluginto generate interesting build numbers.

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

Once you find out that the build is stable (e.g. pass acceptance tests) you can push the version to Nexus or other repository. Any unstable builds just go to trash.

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