Using SourceVersion and rev:r in TFS2015 build names - tfs

We have a process we worked out with our XAML builds that used the TFS change set number in the name of the individual builds. We are trying to convert some of these builds to the new build system on TFS 2015 and running into issues getting change set into the build name.
If we use $(Build.SourceVersion)$(Rev:.r) in the Build Number Format field of the build definition, we get an output of C12345.1 on a triggered build, but then .1 on a manually queued build. We would expect to see C12345.2. Lots of research boils down to, $(Build.SourceVersion) has to be manually entered when the build is queued in order for it to be populated when the Build Number is calculated.
Ok, so we dropped into PowerShell to try to manipulate the build numbers. Once in the PowerShell task, Build.SourceVersion is populated with the correct value. We tried having the Build Number Format of the definition just be $(rev:r), which allowed us to get it in PowerShell, combined it with the Source Version value, and using the result to update the build number via the logging command Write-Host "##vso[build.updatebuildnumber]"$buildVersion. This gives us an output of 12345.1 on both the triggered and manual builds, but rev:r never increments, since there are no builds matching the pattern found in the Build Number Format at the time it is calculated. So manually queuing the builds ends up with any number of them that have the exact same name.
Does anyone have a recipe for getting a build name that reliably contains the Source Version and Revision values where everything increments correctly for both triggered and manual builds?

No, It's not able to do this. You need to understand the token $(Rev:.r) first:
What is $(Rev:.rr)?
To ensure that every completed build has a unique name. When a build
is completed, if nothing else in the build number has changed, the Rev
integer value is incremented by one.
Source:MSDN
In your scenario you set the build number format as $(Build.SourceVersion)$(Rev:.r), if the value of $(Build.SourceVersion)changed, then the value of $(Rev:.r) will not be incremented, it will always keep "1". Only the value of $(Build.SourceVersion) keep the same, then $(Rev:.r) will be incremented.
Besides, based on my test, the variable $(Build.SourceVersion) in build number format is only available when builds were triggered automatically on commit/checkin (on Continuous integration). It can not be resolved when you queue build manually and keep the Source Version field as empty (by default it will get the latest version). So, if you queue build manually, then you need to specify the specific Source Version (e.g C458) in the queue build dialog.
However if you want to set the builds name as incremental ones, you can update the build number manually with the REST API:
PATCH http://server:8080/tfs/Collection/Project/_apis/build/builds/{buildId}?api-version=2.0
Content-Type: application/json
{
"buildNumber": "TEST.20170123.1"
}

So after much research and trial & error this is the closest we managed to come to our desired output...
The Build number format is set to $(Build.SourceVersion).$(Build.BuildId) in the configuration.
We use a powershell script to parse the Assembly File, Source Version, and Build Id to come up with a full 4 part version number in the form of Major.Minor.ChangeSet.BuildId.
We push this new version number back to our build number using Write-Host "##vso[build.updatebuildnumber]"$buildNumber
We also used the Assembly Info step to push this calculated version number back to the actual build process, so that the DLLs come out with the same version number as the build.
This gets us a version number that is unique for each build, and points back to specific a particular state of the source, which was the priority. What we lose is the nicely incrementing build numbers that reset with each change. Instead we have a number that increments for every build that occurs anywhere in the system, and never resets.

Related

TFS 2015 Build vNext $(Rev:.rr) stuck at 1

The New TFS Build System (vNext) does not come with a versioning function "out-of-the-box" so, to supply that, there are tutorials such as this one:
http://incyclesoftware.com/2015/06/vnext-build-awesomeness-managing-version-numbers/
Where you can see that Microsoft actually supports this with an example Azure Script: https://msdn.microsoft.com/en-us/library/vs/alm/build/scripts/index
So far so good. However, by following those exact steps, my build number now has the REV value stuck at 1. That is, no matter how many builds I do in a row, they all have the "01" stuck at the end.
If I remove the specific "Build Number Format" command (Edit Build Definition > General > Build Number Format), that is:
$(BuildDefinitionName)_$(MajorVersion).$(MinorVersion).$(Year:yy)$(DayOfYear)$(Rev:.rr)
it does increment the version but with the default numbering that TFS2015 uses for builds.
As far as I understood, the REV value increments automatically, so much that there is no possible way of changing it, as we can see in this SO Question: TFS 2015 vNext force build number
So, my question is as follows: is there a parameter that is not listed or missing somewhere that actually prevents the Rev value from increasing? Maybe is there a problem on my installation?
Please note that this happens within the same day, so the rest of the build name does not change in order to justify it remaining at "01".
Thanks in advance for any help or advice.
There is a known issue with VSTS and TFS 2015 where the revision counter doesn't increase when certain special characters are part of the name of the build definition. E.g. [].
You must make sure all the value of your build name except the rev:.rr are all the same.
If nothing else in the build number has changed, the rev integer value is incremented by one. Otherwise, the rev value won't change. So please double check the name of your builds, if the rev value have "01" stuck at the end and nothing else changed with the other values of the build number, it's impossible. If it exists, please add the screenshot, this maybe a bug.

How to clear "changed" state in TFS for build schedule or change changeset time?

We have our projects configured with MSBuild script customization to modify the ApplicationVersion property in the project and copy that into the AssemblyInfo.cs file when the project builds. The problem is that we have TFS set up to run on a nightly schedule, with "Build even if nothing has changed since the previous build" unchecked. But since TFS itself is producing this version update, it will rebuild and increment every night. So this is sort of an infinite loop of our own design, but trying to figure out how to get out of it.
If the "changed since the previous build" detection is based on the history timestamp, ideally it'd be nice if when the version gets updated and commits to TFS it does it with a timestamp that precedes the build time. Is that even possible?
If the "changed since the previous build" detection is based on some boolean/bit flag, is there a way to reset it?
Using TFS 2012.
I'm assuming that you're checking in the new version of the assemblyinfo.cs once it's been updated, and this is why TFS is queuing a new build. Have you tried adding a comment to the checkin of ***NO_CI*** This will definitely suppress a CI build but I'm not 100% certain if it will work in your scenario.
Another option is generating the version number via an algorithm rather then just incrementing a counter and checking it back in to Version Control. This circumvents the issue of a new build being triggered
i.e if your version number looks something like
1.2.3.4
Where 1 is Major (modified by a human not the build process)
2 is minor (also modified by a human)
the final 2 digits are then updated by an automated process.
You could use number of days since January 2000 for digit 3 (an arbitrary number but something that would change on a daily basis) and either the latest changeset number in Version Control or the total number of builds performed by TFS for digit 4.
This would fulfill 2 requirements, that version numbers are unique for a given build of an assembly, they always go up.
I would suggest that you don't check the new version number into TFS. There is no value in having the version number in there.
I typically set the checked in assembly info numbers to all zeros. ( 0.0.0.0) and never update them except locally for the build.
This gives you the benefit of always being able to identify locally built DLLs.

TFS: How to reset BuildDetail.BuildNumber?

Simply, I have created multiple builds in Main Branch. However, BuildDetails.BuildNumber is same and incrementing.
I know if I branch my code, it would reset to 1.
Q: Is it possible to reset this number for each build without creating branches?
Update: The only option I find up till now is to save my BuildNumber in Version.txt, checked into TFS repository. Checkout this during build, get the number, increment it, use it in versioning, and Checkin the file. However, still looking for some better solution.
A bit unclear on what you're after. Let me try to explain how build numbers work:
Build "numbers" are generated using the Build Number Format build definition parameter, which by default is $(BuildDefinitionName)_$(Date:yyyyMMdd)$(Rev:.r). The $(Rev:.r) part automatically increments, and resets back to 1 when the day change (all this happens separately for each build definition). AFAIK there's no way to reset $(Rev:.r), nor should there be, because that would case multiple builds with the same build number, which would be confusing.
Rather than having your version number stored in source control you can use the build number generated by TFS.
If you change the format from "$(BuildDefinitionName)_$(Date:yyyyMMdd)$(Rev:.r)" to something like "$(BuildDefinitionName)_1.5.$(YY)$(ddd)$(Rev:.r)" then you can set it as part of the build definition.
You can then parse out this number and use it to version your application, and change it how you like by branch, or whatever.

Can Visual Studio Project files override TFS generated build numbers?

I am using TFS 2012 and the OOTB default build template. I have a build definition that uses the default Build Number Format of:
$(BuildDefinitionName)_$(Date:yyyyMMdd)$(Rev:.r)
For some reason, the revision number generated by TFS is really, really large. For example the last build was PrintOps-Main_20140626.124829.
Only one of my other builds definitions produces builds with such a high revision number. That other build is CI build of this same solution. This leads me to believe that there is something in a project file that is overriding the TFS build number with some custom logic. But I don't know if that is even possible. All other build definitions' revision numbers start out at 1 and increment the revision number by 1 if a build is ran multiple times a day. These build definitions also increment by 1, but they start out at 1248xx.
As troubleshooting I have tried different process templates and modified the Build number format. Everything works as expected except the $(Rev:.r) portion. As soon as I introduce the revision portion back into the build format, I get a very large number.
Is my suspicion correct that it must be some sort of override in a project file? If so, any suggestions on what to look for? There are several (15+) projects in this solution so any advice is appreciated.
I retried the build on a different day and pulled out individual sections of the build number format ($BuildDefinitionName,$Date,$rev) to test each piece individually. I don't know if it was because the new builds were occuring on a different day or if using just $(Rev:.r) with nothing else in the build number format reset things, but I finally got the build number to come out correctly.

Jenkins share build number across jobs?

We are currently developing an app with multiple parallel streams of development. We have a Jenkins job to build each stream/release. So Job-A may be building release 1.1, and Job-B may be building release 1.2.
I think it would be best to have the build number shared across each release, such that if Job-A runs with build number 125, if Job-B runs next it will run with build number 126. The reason I think this is the best strategy is that this is an Android app, which requires its versionCode parameter to be incremented each time it's submitted to Google Play. We use the Jenkins build number for the versionCode value.
Is there any way to configure Jenkins to share a build number across multiple jobs? Or, has anyone come up with a better solution to this problem?
short answer use timestamps or manually set versionCodes, keep things out of the CI server when not necessary. Or force the jenkins build numbers.
long answer I like jenkins to be responsible for automating something that also works on its own. So if I don't need jenkins for the setup, I am happy as well.
Also if you use 2 branches, you probably commit in random orders into them. Trying to tie the jobs together in some ways seems like an unnecessary trouble that could be a problem later on. E.g. what if version 2.0 is built and QAed now, just waiting for the proper release date and marketing team to complete its job, but you need to release a v1.1.1 quick fix after that ? Depending on the solution you pick, you may need to trigger some rebuilds to force a versionCode bump. New build, new QA ?
Your real requirement for the versionCode is for it to be higher than the previous release.
From http://developer.android.com/guide/topics/manifest/manifest-element.html
android:versionCode An internal version number.
This number is used
only to determine whether one version is more recent than another,
with higher numbers indicating more recent versions. This is not the
version number shown to users; that number is set by the versionName
attribute. The value must be set as an integer, such as "100". You can
define it however you want, as long as each successive version has a
higher number. For example, it could be a build number. Or you could
translate a version number in "x.y" format to an integer by encoding
the "x" and "y" separately in the lower and upper 16 bits. Or you
could simply increase the number by one each time a new version is
released.
So here are 2 solutions:
manual bumping. In our projects, I use some sed scripts to automate the bumping of the build number before release. As I also need to change a few things by hand, like versionName prefix, disable/enable debugging mode during development, etc, I manually run a bumpversion script so that next build in my branch has appropriate version and versionCode numbers. Note I use the jenkins build number in versionName instead. This solution prevents you from having the 1.1.1 needs to be out after v2 is ready problem if you pick a large enough versionCode bump for v2.
another more automated yet still simple solution would be to use something out of timestamps. The format YYMMDDHHSS is good enough of an integer (< 2^31), and chances are that whatever version you are going to release next is going to be prepared after the previous one and not within the same minute. So basically when you build v1.1, it gets e.g. 1308131600 and if you build v1.2 the minute after it gets 1308131601. (this obviously doesn't help you against the v1.1.1/v2 scenario)
Here are some ideas for scripts to generate/update versionCode Auto increment version code in Android app.
The jenkins way
Now if you still want jenkins in charge, a simple solution is to use something like https://wiki.jenkins-ci.org/display/JENKINS/Next+Build+Number+Plugin and configure your per branch jobs to have a large enough prefix to ensure no clash. The setup is still pretty simple.
E.g.
110000 for branch 1.1
120000 for branch 1.2
You could look at the multijob plugin where you can add multiple parameterised jobs in to a containing job
https://wiki.jenkins-ci.org/display/JENKINS/Multijob+Plugin
You could also look at artifact archiving Archive the artifacts in hudson/jenkins and then pick the files up later
I haven't tried it, but i'm thinking about going on to the build machine and in each of the jobs replacing the nextBuildNumber file with a symlink to a single file somewhere. What could possibly go wrong. Well, concurrent access might be an issue. There might be an issue if Jenkins re-creates the file from scratch, ie with a remove and a create, instead of just opening it as normal.

Resources