2

Gitflow introduces several branches like develop, release, hotfix, and also encourages feature branches.

In a Maven project, you usually build SNAPSHOT and release versions, and often number them with semantic, three-digit versions.

It would be sensible to automate the build process as much as possible, but the question is: When should we build a SNAPSHOT version, when should be build a release version, when should we build none of that at all?

I image the following could be sensible:

  • Whenever a feature branch is merged back into develop, a SNAPSHOT build is triggered and deployed to the Maven repository.
  • When a release branch is created, as release build is started.

But there are much more situations:

  • When I fix bugs on the release (or hotfix) branch, do I always want a new release build?
  • During developing a feature, should I build on the feature branch? If so, what should this version be called (1.2.3-FEATURE1-SNAPSHOT?)?
J Fabian Meier
  • 33,516
  • 10
  • 64
  • 142
  • From my point of view it drills down to the question: Do you use those built artifacts as a dependency in other project? Furthermore what kind of versioning strategy do you use? (semantical version?) The version is only interesting if you using that as a dependency otherwise no change is need and no deployment into a repository manager is needed... – khmarbaise Mar 26 '20 at 20:18

1 Answers1

4

Let's start with releases. Whether a version is going to be released or not is decided in the future when an already-built binary is deployed to TST envs and checked. When committing or building you can't predict whether the version will be a "release".

Once you abandon these ideas things will become much simpler. And since you can't use branch-based versions for releases, what's the point of making things different for feature branches? You might as well forget about mixing the concepts of branching and versioning together.

With Continuous Delivery (you can borrow its ideas even if you don't use it to the fullest) any build may potentially go to PRD, thus:

  1. Build a binary with any type of versioning that you like. With Maven the easiest is to stick with SNAPSHOT* and never use "release" ones. It's unique, it's standard, it has some advantages with Nexus (retention policies).
  2. When you're ready to go to PRD and the release version is chosen - tag it somehow. It can be a CI Job that keeps track of all PRD deployments; or you may have a page with all the release versions; or you may transfer the binary to another Maven repo (still can be a SNAPSHOT type). The latter is convenient if you go with retention policies for the snapshots.

Also we usually want to mention from which commit the binary was built. You can put this into the binary (some kind of version.properties) during the build time. You may even create an endpoint in your app that servers this version for convenience.

PS: if you simply want to follow GitFlow advice - there is an example of how you could version. But you'll have all the problems (and more) that you already mentioned in the question.

* Maven automatically resolves SNAPSHOT versions into timestamp-ones. But you can't actually use this functionality because the timestamp is going to be different for different artifcacts during the build. If you want to keep version the same across all the binaries in the build you need to generate and assign a timestamp version manually using versions:set. It's not complicated, but is worth mentioning.

Stanislav Bashkyrtsev
  • 14,470
  • 7
  • 42
  • 45
  • Thank you for your thoughts. Frankly, I do not like the idea of putting SNAPSHOTs into production. We don't do this at the moment and seems to go against Maven. Furthermore, without keeping track of the timestamp, you cannot easily make sure which version is deployed. – J Fabian Meier Mar 25 '20 at 20:54
  • SNAPSHOTs go against Maven only when used as is, when you literally write SNAPSHOT in a dependency - because this leads to unrepeatable builds. Same as ranges. A *resolved* snapshot (looks like `0.0.1-20101204.150527-6`) on the other hand is a perfectly good version - and it *does* contain a timestamp. BTW, Maven was created before CD was described, so not all its ideas may be up-to-date (Maven Release Plugin is a good example). – Stanislav Bashkyrtsev Mar 25 '20 at 21:26
  • @StanislavBashkyrtsev you might need to take a look into most recent Maven Release Plugin https://maven.apache.org/maven-release/maven-release-plugin/ The problem with timestamp SNAPSHOT is that the are identified as release from Maven point of view and not from repository managers point of view which might cause other issues. – khmarbaise Mar 25 '20 at 23:02
  • I've used Snapshot versioning in 2 organizations for 6 years - it worked very well and didn't cause any problems. If you ask Nexus for a timestamped version - it will give you that version (not the latest available SNAPSHOT). – Stanislav Bashkyrtsev Mar 26 '20 at 05:48
  • But again - you *can* use release versions, I've tried that before and it worked too (you won't get some nice snapshot-only features from Repo Managers though). E.g. you can use Build No and Commit hash, or you can use a timestamp and upload to "releases". But you still need to generate a version of the same format for *each* build. – Stanislav Bashkyrtsev Mar 26 '20 at 05:54
  • I'll upvote but I still wait for answers that are a better fit for my situation. – J Fabian Meier Mar 26 '20 at 08:21
  • @StanislavBashkyrtsev From my point of view you are misusing SNAPSHOT's (on repository manager side)..So you are building releases..so why not using releases...cause SNAPSHOT repos will be cleaned up after time (of course you change the configuration etc.) building a version is not hard.. – khmarbaise Mar 26 '20 at 20:16
  • @khmarbaise, that's exactly why I use SNAPSHOTs - I want those artifacts to be removed after some time. I'm usually constrained by how much disk Repo Manager has. If I have 10 projects and only 200Gb - I'll get out of space at some point. That's why I set up 2 snapshot repos: `builds` - artifacts that will expire and get removed; `builds-released` which keeps artifacts forever. If release happens I move the artifacts from `builds` to `builds-released`. – Stanislav Bashkyrtsev Mar 26 '20 at 20:51