TeamCity Custom Build Number - AssemblyInfo patcher - powershell

I have created a TeamCity build configuration which suits my needs, see build log below:
It's all working great except for 1 thing - Custom Build Number. My build number format is as follows:
Major.Minor.BuildCounter.TodaysDate, i.e. 2.0.59.20160224.
I achieved this with a PowerShell script.
Notice in the build log, Step 1 is to Set Build Number. Problem is that this happens after the Update assembly versions step. So this version number does not get applied to my assemblies.
But the correct version number is used everywhere else in the build process.
So my question is, HOW do I set the Custom Build Number before AssemblyInfo Patcher runs?

Resolved using Snapshot dependency feature of TeamCity.
Created a build configuration called Version. This has a powershell script build step which creates my desired build number.
Next, I make my actual build configuration dependent on the Version build configuration.
Then I get this build number in my actual build configuration, like so:
%dep.[Build Configuration ID].system.build.number%

Teamcity provides build feature "AssemblyInfo Patcher" which allows setting a build number to an assembly without having patch.
You may find it under :
Build Configuration Settings -> Build Features -> click on add new feature and select AssemblyInfo patcher.
You may assign same build number format "Major.Minor.BuildCounter.TodaysDate" AssemblyInfo Patcher. something like : %Major%.%Minor%.%build.counter%.%system.build.start.date%
By adding Major and Minor as teamcity configuration parameters.
You may use teamcity's predefined %build.counter% parameter.
And finally TodaysDate:
The Groovy Plugin for TeamCity provides build start date/time properties
system.build.start.date
system.build.start.time

Related

Build and Deploy pipelines with same version

I would like to specify the (SemVer) version number during a (not selfhosted) DevOps release, so that DLLs will have this version number embedded in them, and I can create a release to GitHub + NuGet with the same version.
However, I'm struggling with how to accomplish this with as much automation as possible.
I know I can use the /p:Version=x.y.z during build to set a specific version, but if I build one more time I shouldn't use the same version number again, which could be fixed by appending +buildnumber to the version. This build number is not something I neccessarilly would want in the actual release, though.
So, how should I best handle version numbers during build and deploy, without having to edit some variables every time?
how should I best handle version numbers during build and deploy, without having to edit some variables every time?
If you want to increment the version in build/release automatically, the buildnumber should be a good choice.
In generally, we defined the major.minor.patch in Variables or some config file, and use it with BuildNumber in the Build number format option:
Then, we could use the option use the build number as nuget version when we pack the nuget package:
For the release, we could use the parameter $(Build.buildnumber) to get the build number and set it as release version:
Now, we could handle version numbers with same version during build and release, without having to edit some variables every time.
Hope this helps.

Azure DevOps - Set a Build variable using another variable (nested/composed variables)

In Azure DevOps I have a Pipeline variable "package version" and I set it using 0.1.3$(Rev:.r)-alpha .
I use that variable to replace the "Version" in the .net core project file.
In the Build tasks the dotnet build give me this error:
so I assume the Pipeline variable cannot use a nested variable.
There is a nother way or a different syntax to do it?
[Edit]
The nested variables should work.
I think the error was the dotnet pack using Automatic package versioning set to "Use the build number" that contain the wrong $(rev:.r) (lowercase!).
Using a custom string for Version in the VS project file gives noise on VS (error if the file is open, warning otherwise) and now the Pipeline Build give me an error on dotnet nuget restore because of the invalid Version.
I decided to use a simple clean version, <Version>0.1.2</Version>, that I can choose and document.
Then I want to find a way to read it in the build pipeline and create a custom variable attaching the Build Revision:
0.1.2$(Rev:.r) => 0.1.2.123
That is the result I want.
I found this: https://marketplace.visualstudio.com/items?itemName=tmarkovski.projectversionasvariable
I'm using it with the default settings.
I'm using the variables it creates to compose a new variable, "package version":
and I use that in the nuget pack task:
but it does not work.
The resulting variable still contain "$(Rev:.r)" not parsed.
I'll try to use again the "Automatic package versioning" and create the build number in the Options...
[Edit 2]
Set the build version number in the Pipeline Build Options worked.
It's not the optimal solution because the Build Number is not parsed and looks awful.
[Solution]
$(Rev:.r) is not available outside Build / Options.
I used $(Build.BuildNumber) and I'm able to create a composed variable:
$(Version.MajorMinor).$(Build.BuildNumber)-alpha
Build.BuildNumber is valorized in Build/Options: $(Build.DefinitionVersion)$(Rev:.r)
Version.MajorMinor is created by the Project Version As Build Variable add-on.
I don't know how to obtain the same result without using a third party component.
I'm glad my extension helped and thanks for the nice review. If you want more control and have a little time to spend to play with PowerShell, you can easily achieve what you want in two steps, without using third party extensions.
Read and parse the .csproj file as XML
Set build variables
Here are couple of links on reading XML files and working with build variables, it's actually pretty easy.
https://www.business.com/articles/powershell-read-xml-files/
VSTS: Pass build/release variables into Powershell script task
[xml]$XmlDocument = Get-Content -Path $env:project_file
echo $XmlDocument.Project.PropertyGroup.Version
https://learn.microsoft.com/en-us/azure/devops/pipelines/process/variables?view=vsts&tabs=yaml%2Cbatch
Write-Host '##vso[task.setvariable variable=package_version;issecret=true]0.1.2.'
Note: my answer wouldn't fit in a comment, I had to post an answer.

Using sln.DotSettings in TeamCity dotcover runner

I am using an NUnit 3 runner in a TeamCity 9.1.6 step. I've chosen "JetBrains dotCover" as the .NET Coverage tool, and now I'd like this step to use the xxx.sln.DotSettings file that we've put in source control and that we're sharing across devs in Visual Studio, rather than to duplicate settings to TeamCity Filters, Attribute Filters etc. Is this possible in TeamCity?
It is not possible from the box now. It is a great idea, could you create an issue here https://youtrack.jetbrains.com/
But there is a simple workaround:
you could parse dotSettins manually on the first step
publish configuration parameters using ##teamcity[setParameter name='ddd' value='fff'] TeamCity service message (see for details https://confluence.jetbrains.com/display/TCD9/Build+Script+Interaction+with+TeamCity)
use those configuration parameters in the appropriate fields for dotCover like %ddd%

Mix existing and AssemblyInfo patcher generated version info in TeamCity builds

I've enabled a "Build Feature" called "AssemblyInfo patcher" to tweak the version of DLLs generated by my TeamCity builds. I've remixed info from this other question and came up with this Assembly version format setting:
1.0.%build.vcs.number%.%system.build.number%
Now the final thing I would like to achieve is have the Major (1) and Minor (0) come from the original files, instead of hard coding them into TeamCity.
How can I do that?
I've guessed / tried:
{1}.{0}.%build.vcs.number%.%system.build.number%
But this gives an error. I've tried:
%build.vcs.number%.%system.build.number%
But this generates the vcs.number and build.number as major/minor instead of build and revision number, so e.g. 1234.21.0.0.
I've read the AssemblyInfo patcher documentation but it doesn't explain much at all.
I've skimmed the available variables (with the icon to the right of the input field) but found no relevant variables.
How can I set up the "AssemblyInfo patcher" so that:
Major and Minor are kept as they are in the source files;
Revision is the VCS revision number;
Build is the TeamCity build number.
If it's possible at all?
You can use File Content Replacer. It provides the ability to reference capturing groups of the regular expression and change only specific parts of AssemblyVersion attribute.

How to differentiate TFS Builds and manual builds using macros in Post build event

In TFS post build script of a .proj file I want to find whether the project build is happening through TFS triggered build or manually triggered build.
Can someone suggest me how to do this using macros in Post Build event.
Short answer: you can make use of the IsDesktopBuild MSBUILD property within your csproj file to differentiate between TFS and local build.
Long Answer:
Developer or Team Build?
To differentiate the build environments we have to implement a mechanism that detects in which environment the build is being executed. In other words, we need to know if we running a local build that is executed by the developer or a team build running on the build server.
In fact, there are 3 different build environments we need to consider:
· Visual Studio Build – a build executed by a developer, on their own development machine inside the Visual Studio IDE
· Team Build – a build executed by TFS (manually or scheduled), on the build.
· Desktop Build – a build explicitly executed manually, on the development workstation using the command 'msbuild.exe tfsbuild.proj'.
A ‘DesktopBuild’ and a ‘TeamBuild’ are very similar in nature except that ‘DesktopBuild’ does not perform a ‘GetLatest’ function from source repository, will not ‘Label’ the source tree and will not determine the change set.
When using MSBUILD tasks (as we will use primarily in following sections), one common way to achieve this is to use the ‘IsDesktopBuild’ and ‘BuildingSolutionFile’ properties as conditions to test in the tasks.The ‘IsDesktopBuild’ property is declared in the ‘Microsoft.TeamFoundationBuild.targets’. The ‘BuildingSolutionFile’ property is declared and assigned automatically by MSBUILD.
The following table lists the values of each of these properties in each of the build environments.
Environment IsDesktopBuild BuildingSolutionFile
Visual Studio Build (empty) (empty)
Desktop Build true true
Team Build false true
One caveat with using the ‘IsDesktopBuild’ property is that it is not defined in many target files by default. This property will have an ‘empty’ value in a Visual Studio build, so we initialize it to a value of ‘true’ as the default value. Therefore we need to be explicitly define it in all MSBUILD target files where it will be tested.
We simply add the following element to all target files where we need to differentiate between a build on the development machine and a build on the build server (within the first section).
<IsDesktopBuild Condition="'$(IsDesktopBuild)' == ''">true</IsDesktopBuild>
Update: thank you #dbardakov. Starting VS 2012 we can use the property to find if the build is happening within Visual Studio:
BuildingInsideVisualStudio
MSDN SOURCE - for BuildingInsideVisualStudio
MSDN SOURCE