Build versioning in continuous delivery
Asked Answered
H

3

44

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.

Hyehyena answered 20/11, 2015 at 7:26 Comment(2)
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?Alcheringa
The question is probably a better fit for programmers.stackexchange.comAlcheringa
M
46

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.

Magnify answered 20/11, 2015 at 8:13 Comment(6)
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?Absolute
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.Magnify
For reference, this is a cleaned up version of our script which bumps the version number for one of our projects: 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.Magnify
Can you elaborate on why "you should never modify your code from a CI process" is true?Multiplier
@Multiplier 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.Magnify
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?Barrault
V
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.

Vaud answered 6/6, 2021 at 17:54 Comment(3)
"Always tag your repo when producing a deployable artifact" -- with what version number? Who owns the release version number (which might be different from the code version number)? Who makes the decision of whether or not a release constitutes a major release vs. a minor release? (Not all release with non-breaking changes are necessarily a minor release. If enough new functionality is included, the "release manager" may decide to make the release a major release. This happens all the time.)Finding
@Finding - 1) The version number that u r applying to your exes and libs. 2) Ideally there would not be a different ident for a release but that depends on your org needs and what you are making. For ex "Windows 95" (a release identifier) was a collection of progs that each had their own version number. 3) This is up to you and your org. Usually there will a method to follow like semver that guides this determination. Dont let the tail wag the dog on versioning, a release identifier is just a friendly name applied to sw after its been built. It has market value, but thats it.Vaud
"Don't let the tail wag the dog" - Generally, a good idea! In my organization, though, there is a hierarchy of versioning numbers: binaries, packages, release, Core product marketing version, customer product binaries version, customer product release version. We have a Core app that is built by the R&D group, and each customer may have multiple customized instances of the app running in production (due to what our app does, we have this complicated environment, and hence, versioning). We don't version well--so this issue is near and dear to me. But your answers are on point.Finding
M
-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.

Manna answered 25/12, 2020 at 3:55 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.