- One small but very useful library.Includes general functionality – logging, working with Windows Azure, etc.
- Large number of projects(solutions) where this library is used.
- Distributed team of developers, some of whom write and maintain the library, and another part just uses it.
Problems you want to solve
- Need to copy sources/binaries from project to project – inconvenient, long, the possibility of errors when updating.
- Inability to use different versions for different projects – finding and building a particular version "from the past" is inconvenient, again there is a high probability of error when upgrading.
- The need to keep track of library dependencies – especially the Azure SDK, which is now regularly updated, not always all developers have the latest version, and updating the SDK is not always possible.
- Using an existing project on different machines is another "thin" place that generates a lot of unnecessary bugs.To work correctly, the paths for the projects must match completely, which is very difficult to achieve.
Solution method and problems encountered
It immediately became clear that the easiest way to get a package with the latest/concrete version of a library when building a solution is through NuGet – working with the Azure SDK has a similar approach.
However, after the deployment of the repository it turned out that just publishing in NuGet is not possible – I had to write a separate project that would build the package for publishing and uploading it to the repository.
We also found out that the version number in the file
AssemblyInfo is not very handy – the default numbering does not include the publication date, which somewhat complicates the solution to problems that arise after updating the library (it is not always easy to catch when this or that part of functionality has stopped working).
In the end it was decided to move the publishing process to a TFS server, adding a Build Definition(build) for the library.All the mentioned steps were performed in Team Explorer VS 2010, but I haven’t noticed any differences when moving to VS 2012.
Search for the best
The supporting project chosen was NuGetter (to automatically publish to the repository during the build on the server) with the addition of TFSVersioning (to edit the file
AssemblyInfo during the build on the server), author projects have one, and there shouldn’t have been any problems with integration.
Step by step description of personal implementation experience
I’d like to point out right away that everything written below is following the documentation from both projects, plus a description of some side-effects I encountered.
I personally haven’t had to customize the build before, so all the steps will be described in a fairly detailed and nerdy way.
0. Preparing to set up – pouring to the server.
Both projects contain libraries with defined Custom Actions for the build workflow on the server and xaml-files with workflow templates to extend the default build features.All you need to put on the server: project templates to be able to select them when creating a new build, and libraries to be able to find them the next time you run this very build.
It is recommended that workflow templates be placed in the default template storage folder
It is recommended to put the libraries and NuGet.exe file with its settings in a separate folder (on our server it has a very original name
nuget – but it’s always on top, which is convenient when configuring the build).
For these libraries to be found during the build process, you need to configure the Build Controller for the solution. This is done as follows :
Team Explorer –> (Solution Name) –> Builds –> right click –> Manage Build Controllers…
Controller Selection :
Editing Controller for (Solution Name):
In the field
Version control path to custom assemblies you need to specify the path to your shared libraries folder.
Here’s where I had my first little problem: I was trying to edit the properties of not of a controller, but of one of its build agents Pay close attention to.
Just in case, check the connection to the folder (button
Test Connection ).
After checking the connection, save the changes.
1. Adding a new build based on the template.
Now you need to add a new build using the template that was loaded in the previous step. This is done like this :
Team Explorer –> (Solution Name) –> Builds –> right click –> New Build Definition…
Name and description of the bill :
Schedule to run the build :
- Manual start only.
- After each check-in from developers.
- Waiting for the previous build to complete.
- Assembling check-in, with an option to set the start time to "no more than N minutes".
- Accept check-in only if there was a successful merge and the server build was successful after that.
Code to be collected during the build :
Sometimes there are too many projects here – remove unnecessary ones. You can also specify which project should be copied to which folder during the build.
Define the default settings for the build :
It is necessary to select :
- The controller that was configured in the previous paragraph.
- Where to put the code :
- Do not copy the result of an assembly anywhere.
- Copy the build result to a shared folder
Requires correct UNC address of the form
- Copy the build result to the TFS-server folder
This option is not always available, depending on the privileges of the user creating the build.
Bill Settings :
The first three items are settings that are always available for any build. Right now, only the first block is of interest to us – selecting projects or build solutions (
Projects to Build ).
Also worth looking at
Build number format – this parameter is the name of the build folder (it should not be too long for projects with many nested folders).
Settings for saving build results :
2. Selecting a template for the build.
On the tab
Process at the top of the drop-down list you need to select the required template. If you don’t see the required one in the drop-down list, it means that it will be used for the first time, and you need to "show" it to the server using the
New... (select or copy already loaded file on the TFS-server).
Pudding, this is Alice, Alice, this is pudding.
Template selection :
- [All the build templates installed on the TFS server].
VersioningBuildTemplate.xaml– Basic template for replacing versions in AssemblyInfo.cs file.
VersioningBuildTemplate15.xaml– template to replace in AssemblyInfo.cs file – additional library property editing options, available in TFSVersioning 1.5.
NuGetterStandardBuildTemplate.xaml– A basic template for publishing build results to NuGet.
NuGetterVersioningBuildTemplate.xaml– Basic template for publishing build results to NuGet and replacing versions in AssemblyInfo.cs file.
NuGetterVersioningBuildTemplate15.xaml– Template for publishing the build results to NuGet and replacing in AssemblyInfo.cs file with additional features from TFSVersioning 1.5.
3. Setting replacements in AssemblyInfo.cs file.
If a template involving TFSVersioning has been selected, the build settings will show
What and what is it for :
- The first two lines are responsible for the version number templates for
- Replacement Rules for Version Number Template :
- The number occurring anywhere in the pattern remains unchanged.
Bis replaced by the build number within one day.
YYYYare replaced by a 4-digit representation of the current year.
YYare replaced by the 2-digit representation of the current year (last two digits).
Mare replaced by the number of the current month (when replacing
MMzero is not put in front ).
Dare replaced by the number of the current day in the month (when replacing
DDzero is not put in front ).
Jis replaced by the date in the format
DDD– is the sequence number of the day since the beginning of the year.
The suggested default pattern is
1.0.J.B – provides an almost unique version number for the library.Difficulties will begin after 100 years, provided the major and minor versions of the project are maintained. Legacy code strikes back.
BIt can be used in case of setting several builds for one project – we add 100 to one, 200 to another, and everybody is happy. Maximum value for the sum of build number and prefix is 65535 The author of the projects also asks to contact him if you produce more than 999 builds a day, you are obviously doing something interesting.
AssemblyVersionin their absence.
If you build more than one project, or if you build a NuGet package as well, you can put templates for version numbers in a separate XML file and upload it to the server and enable it on line 7, specifying the path to it on line 8.
The XML looks like this :
<?xml version="1.0" encoding="utf-8" ?> <VersionSeed> <Solution name="Default"> <AssemblyVersionPattern> 1.8.j.b</AssemblyVersionPattern> <AssemblyFileVersionPattern> 1.8.j.b</AssemblyFileVersionPattern> </Solution> <NuGetPackage id="ServiceLib"> <VersionPattern> 1.8.j.b</VersionPattern> </NuGetPackage> </VersionSeed>
If you are using the build template for TFSVersioning 1.5, you will also have
tab with additional autocomplete options in the AssemblyInfo file:
4. Setting up publishing in NuGet.
Three more tabs are available when using the template for NuGetter.
NuGetter (A) – Pre-Packaging:
The first of the tabs is responsible for preparing the assembled project for packaging and publishing. You can add your PowerShell script to the server if needed (to create the folders specified in the NuGet spec, for example).
Be careful: PowerShell executable scripts may be banned for execution on the server. In this case build will not generate an error but will just try to start NuGet as if the script worked correctly.
The policy regarding the execution of PowerShell scripts can be checked and fixed with the commands
NuGetter (B) – Package:
What and what is it for :
- The first line is any additional parameters to run the NuGet file.
- The second line is the name of the base folder for executing NuGet commands when packaging and publishing.
- The third line is the path to the NuGet file on the server ( the file should be in the repository or in the folders specified in the PATH in Windows on the server ).
- The fourth line is the path to the file NuGet specs on the server (the file must be in the repository).
- The fifth line – the name of the folder, where the package will be created (if the build succeeds).
- The sixth line is the address of the file with version templates for the project – as mentioned above, you can put all the version numbers for projects and packages in a separate XML file and not constantly change them in the properties of the build.
I wasn’t able to configure the workflow so that the NuGet file calls to update itself before execution – I just had to upload a new version of NuGet.exe to the server. I think I need to create my own template based on the provided ones, where I add a Custom Action with another NuGet call. Although, maybe I’m reinventing the wheel and it’s much easier to do.
NuGetter ( C ) – Push and Publish:
What and what is it for :
- The first line is the API key, if it is defined for the NuGet repository where the package is published. The author expects the GUID in the entry
aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeeeeeeeeeIf the specified key fails the ReGex check, the string is considered relative path to the file with the API key
- The second line tells you whether you just want to create a package and copy it to the repository or if you want to publish it to a remote server. In fact, when the adds the parameter
-coto NuGet startup parameters, which ruins the whole build, because in version 2.1 the parameter is not recognized.
- The third line indicates whether or not to attempt to publish the package to the repository after it has been created.
- The fourth line is the address of the NuGet repository to publish.
Possible values :
- URL of the remote repository.
- UNC name of the folder on the local network.
- The local address of the folder on the server where the build starts.
We use the standard NuGet Server , without any add-ons.
In order to successfully publish to the NuGet repository it is mandatory to have write permissions to the packages folder for the user under which the Application Pool is running. The memory on the server must also be sufficient, because the error for lack of disk space in the EventLog is very strange and completely uninformative.
5. Running the build.
Except for running the build automatically according to the settings from item 1 , you can run the build manually.
Team Explorer –> (Solution Name) –> Builds –> Builds to run –> right click –> Queue New Build …
Table of running builds with current status :
The problem was solved much faster than this article was written. Moreover, after getting acquainted with the technique of building builds on TFS, it turned out that setting up Continious Integration is not that hard. The important thing to remember is that builds the build on the server , so project settings, files and other changes you need to remember to fill in the repository.
When the build fails, TFS automatically creates a bug, with Critical urgency, and hangs it on the developer who uploaded the code to the server last. After "fixing" the bug is assigned to
Network Service , so this is the user who needs to be given write permissions.
I hope this article will save someone’s time and nerves.
Thank you for your attention.