Pergunta

A product version, such as v1.0.0.100, represents not only a unique production release of software, but helps identify feature sets and hotfix stages for said product. Right now I see two ways to maintain the final package/build/binary version of a product:

  1. Version Control. A file somewhere stores the version number. Continuous Integration (CI) build server will have a script to build the software that uses this checked-in version number to apply it to all areas of the software needed (binaries, installer packages, help pages, documentation, etc).

  2. Environment and/or build parameters. These are maintained outside of version control (i.e. they are not tied to the snapshot/tag/branch). The build scripts distribute and use the number in the same way, however they just obtain the value differently (it is provided to the build script, instead of having the script know where to get it relative to the source tree).

The problem with the first approach is that it can complicate merges across mainline branches. If you still maintain 2 parallel releases of the same software, you will resolve conflicts when merging between the two mainlines if the version has changed on both since the last merge.

The problem with the second approach is reconciliation. When you go back to a release 1 year ago, you will rely solely on the tag information to identify its release number.

In both cases, there might be certain aspects of the version number that are not known prior to the CI build. For example, a CI build may programmatically put in a 4th component that is really the automated build number (e.g. 140th build on the branch). It might also be a revision number in VCS.

What is the best way to keep up with a software's version number? Should the "known" parts always be maintained in VCS? And if so, are the conflicts across mainline branches an issue?

Right now we maintain our version number via parameters specified and maintained in the CI build plan (Atlassian Bamboo). We have to be careful before merging to our master branch that the version numbers are properly setup in advance of the CI build kicking off. With regards to the Gitflow workflow, I feel that if the version number were tracked in source control, we could guarantee it is setup properly when we create our release branch in preparation of the release. QA would perform final integration/smoke/regression testing on this branch and upon signoff, a merge to master takes place which signals commitment to release.

Foi útil?

Solução

Personally, I choose option 3: keep versioning information in VCS metadata, specifically, tags.

Git makes it very easy to do so, because there is a command git describe, which can uniquely describe a commit based on a tag. Here's how it works:

  • If the current commit is tagged, output the name of the tag.
  • Otherwise, walk the history backwards until you find a tag and then output a description in the following format: <tag>-<number of commits since the tag>-g<abbreviated commit hash>.
  • If there are uncommitted changes in the workingtree, append -dirty.

So, if you are doing a release build, and have the commit tagged 1.2.3, it will output 1.2.3. If you are currently working on 1.2.4 and you made 4 commits since 1.2.3, and have uncommitted changes in the tree, it will output 1.2.3-4-gdeadbee-dirty.

This is guaranteed to be unique and monotonic, as well as human-readable, and thus can be used directly as a version string. The only thing you have to ensure is a proper naming convention for tags.

Outras dicas

Yes. It is good practice to keep most of the version number in vcs. If we consider semantic versioning semver.org where we have major.minor.patch.build the first three must live in vcs. The last one can be a incrementing number from your build server used to backtrack the specific commit that a binary is made from.

To facilitate this in .NET we have made a small cmd line exe that is committed to git. With a pre-build event, it picks up the build number which teamcity tagged during build. This cmd line tool auto generates a class with one constant containing the build number. The rest of the version number: major.minor.patch is just a normal constant in another file. These two shared files are included in every assembly in a solution as a link(alt+shift-drag).

This approach is powerfull enough that we can have teamcity build and test our code. Push to azure and have kudu build it again but with the teamcity build number as the version of the dll's.

Licenciado em: CC-BY-SA com atribuição
scroll top