41

I have some concrete questions about versioning in Continuous Delivery. I think I understand global workflow that more or less is this:

1) Code
2) Push to version Control
3) Continuous Integration (unit, integration and end-to-end auto testing)
4) Artifacts deployment

What about versioning? How manage build versions?

Let's say that we are working on a Maven-based project with semantic versioning: major.minor.build.

When developer commit changes to VCS and CI server perform a build, should CI server increment the build version and create a tag in VCS?

Is this build version present in the source code? If so, after each push to VCS, developer should update the project, since CI server committed changes (version increment) on project.

I'm a little confused and I would like to understand the CD workflow in a practical way.

Héctor
  • 24,444
  • 35
  • 132
  • 243
  • 3
    There are multiple ways to approach this, depending on your circumstances and goals one might be better than another. There are numerous "standard" books that cover these approaches ("Release It" being one of them). Start by answering the question: Do you want every build to result in a uniquely versioned artifact. Why? Why not? Or do you "manually" (e.g. after a sprint) decide that it's time for a new version? – reto Nov 20 '15 at 07:42
  • 1
    The question is probably a better fit for http://programmers.stackexchange.com/ – reto Nov 20 '15 at 07:44

3 Answers3

44

In general you should have:

  1. A manually managed version number.
  2. Any number of "reference" numbers.

The first point is crucial if you care about semver or in case you have to provide compatibility information for other tools/libs. It's only you who can tell whether a new "release" breaks anything - the most popular indication system is following the semver versioning rules.

The second point ("reference" number) might or might not be important for you. You usually don't need more than one, the CI/CD build's version number (every popular CI/CD service has a build version number ID which refers to that specific "build"). The point of this number is that you can quickly check the related CI/CD build/logs of an artifact if you need it.

How to merge the two (or more) parts?

It's not uncommon to have separate "version" and "build" numbers. In fact every iOS project have that by default. In that case you have the "version" number managed manually, and a separate "build" number managed automatically. The build number can be in the artifact's name, or can be printed when someone retrieves the --version information in case of a binary (ex: $ brew info -> 0.9.5 (git revision 18c48; last commit 2015-11-02)

Alternatively you can either add new components to semver (x.x.x.BUILDNUM), use the last component of semver (x.x.BUILDNUM - I wouldn't recommend this if you have a strictly incremental BUILDNUM) or simply include the "build" number in the name of the artifact.

These are all possibilities, you'll have to pick the best one for your case. You have to define the meaning of these numbers and decide where the number should be presented (e.g. should it be part of a --version call or should it be just part of the filename).

edit: to reflect on your question about "should CI server increment the build version and create a tag in VCS?" - I would never recommend this. A CI server can have issues too, you should never modify your code from a CI process. Accidentally overwriting (e.g. force pushing) something can be really dangerous. That's why it's better to just use the Build Number exposed by the CI/CD service.

Viktor Benei
  • 3,447
  • 2
  • 28
  • 37
  • 1
    Thanks!! You helped me very much. One more question, If I choose to put build number in artifact and manage manually the version number, I suppose that I should tag in VCS when increment manually the version and not in each build. Am I right? – Héctor Nov 20 '15 at 08:32
  • 1
    Yes, we usually have a script which does that, based in a simple version text file. We run it manually when we want to increment the version number, it increments it in the version file and then creates a commit & tag. You can of course do this manually, but that's more prone to errors. – Viktor Benei Nov 20 '15 at 08:52
  • For reference, this is a cleaned up version of our script which bumps the version number for one of our projects: https://gist.github.com/viktorbenei/d341e74c8321473c8a67 - first it checks if there's anything which is not yet committed, then it proceeds to bump the version number, commit the change and create the related git tag. – Viktor Benei Nov 20 '15 at 09:04
  • Can you elaborate on why "you should never modify your code from a CI process" is true? – stonedauwg Jan 23 '17 at 21:38
  • 2
    @stonedauwg it's more of a generic advise, that if you can avoid it, you should. If you allow a non interactive environment to modify your code it can modify it any way, all you can do is stop the process if you find an issue and try to rewrite the git history. A simple, less harmful example is if a tool changes where it generates the build output and it starts to commit your artifacts (iOS ipa, Android apk, etc.) into the repo, if the new dir is not git ignored. File delete can also happen. Depending on what and how you do, this might not be an issue, but especially for beginners it can. – Viktor Benei Jan 24 '17 at 09:32
  • Thanks for your answer. But, I think there may occur a problem: suppose we have sequentially committed **c1**, **c2**, **c3** to the repo and the CI has built artifacts with 1, 2, and 3 build numbers, respectively. Suppose the c1 artifact (i.e. **build1**) was versioned **1.1** and deployed. Now we want to deploy a new release: tag the **build3** artifact with version **1.2** and deploy; unfotunately a failure occurs after deploy and we have to step back to the **build2**. So the question is: **What version should be used for the build2?** – Emran Jan 18 '20 at 08:44
4

What about versioning? How manage build versions?

The same way you would otherwise; when producing an artifact to be distributed (either to the cloud or via floppy disk) the artifacts and components should be marked with a unique and traceable version number. This number should be directly correlated to the source code that created it. We do this because it helps us to fix problems correctly in production systems, trace program behavioral changes, and a few other support/maintenance/design things. We should be doing it regardless of delivery mechanism because it's easy to do and it can save you a lot of trouble in situations where if you didn't have the ability to connect the source with the executing program, you would be making hard assumptions and guesses (with your job and/or reputation on the line).

So please ignore the advice given in another answer about not tagging your repo - Always tag your repo when producing a deployable artifact.

Also whenever you can, try to make sure the version number that is generated for the build to use is getting set on the program executables or libraries that are being built.

When developer commit changes to VCS and CI server perform a build, should CI server increment the build version and create a tag in VCS?

Most build systems have the facility for versioning or numbering, Maven included. However only builds that produce the artifacts that get deployed should be assigning version numbering and tagging repos. Usually this will exclude Continuous Integration/Gated Checkin builds as they are only for integrating the incoming developers changes with the main branch.

StingyJack
  • 19,041
  • 10
  • 63
  • 122
-1

You will find a detailed solution here

Single click code-versioning (Complimenting cloud-native Architecture)

The idea is to use the maven plugin jgit-flow plugin and using Jenkins and this plugin we have created the whole pipeline to automate this process.

Dhruv
  • 10,291
  • 18
  • 77
  • 126