With our migration to VS 2008 (Beta 2) complete, the next task was to formally adopt an automate build process, and we chose Team Build as the software to drive that process. Previously I had setup CC.Net, as I had used it at a prior job so I was familiar with out. However, there was never a buy in from the whole team, so no one except me really cared when the build broke, or how to go about fixing it.
As part of our migration plan, we have gotten buy in from the entire team (IS) on an automated build process, so for at least a the development and testing level we will have an automated process. The next step after that, is using Team Build to actually automate the deployment to our staging and production environments, such that we can easily deploy small, and large changes in an efficient, consistent, and error free manor.
One of the downsides to development, at least for me, is the task of deploying a change to production. There is usually a lengthy change management process, a number of documented (and un documented) steps needed to do the actual deployment, and then a series of manual tests to run to make sure everything is still working. At a presentation I attended as part of the ARCReady series, the concept of a truly automated build and deployment process was presented, and that concept is what I hope to accomplish (eventually) on my current project.
The first step in achieving my utopia, is to start with a simple build that can be invoked at anytime. I actually have another developer working on setting up the builds for our main project. The project I'm using for this example, is for our smart devices.
To get started, open Visual Studio and select New Build Definition from the Build Menu. This opens up a dialog box with 6 tabs/sections listed on the right, and the tab details on the left. The General, Project File and Build Defaults require information in order to proceed. Workspace, Retention Policy and Trigger all have defaults chosen, but you can change them if so desired. When you are done configuring all of the tabs, click OK.
Build definition name, an optional description, and a checkbox to enable or disable the build. I named the build "ProjectName - All", and entered a short description of what I hoped to accomplish with the build.
You need to select a Source Control Folder, and a Local folder. The defaults are the root of the project in TFS, and a folder defined as $(SourceDir)
Here you select the MSBuild file used to define the build. The default location is $/ProjectRoot/TeamBuildTypes/BuildDefinitionName. If there is no TFSBuild.proj file in the location, you will have the option to created one, which is what I did here.
Choosing to create a new TFSBuild file, bring up a new dialog that will allow you to select a solution in the workspace, 1+ configuration options (i.e. debug or release and target platform), and build options (unit tests, code analysis, etc). I happen to have a solution in this workspace, so I am using it, and chose to build both a debug and release version.
When you are finished with the TFSBuild options, click finsih to return to the Build Definition dialog
Here you describe how builds should be retained, and the values you choose is completely dependent on your individual needs. For now, I'm selecting "Keep Latest Only" for Failed, Stopped and Partially Succeeded, and "Keep 5 Latest" for Succeeded.
You need to specify a default Build Agent (computer running Team Build), and a staging share. I was surprised to see that the Build agent we had already defined in another project, was not available in the drop down list. I recreated it by clicking the New button. I had to sepcifcy a Agent Name, computer name, and working directory (defaulted to $(Temp)\$BuildDefinitionPath)). If you don't want the source downloaded and built from C:\Documents and Settings\TFSServiceAccountName\Local Settings\Temp\Projectname\BuildName, change the working directory here.
Since the team working on this project is a little different, I've setup a different folder/share for this project so that I can assign appropriate share and NTFS rights.
Finally, you can select when to build. Options include manual (check-ins do not trigger a new build), Build each check-in, Accumulate check-ins until the prior build finishes, build every week on the following days.
For requirements, I am choosing the manual build option.
You new build definition should show up under TFSServer\Proejct\Builds in Team Explorer. Right click on the build and choose Queue New Build. Here you can select the build definition (defaults to the build you right clicked on), Build Agent, drop folder for the build (defaults to the folder you chose under Build Defaults), a queue priority, and option MSBuild command line arguments.
My build started, and downloaded all of the source from the root of the Project, which is somewhat undesirable, as it's not all needed. Also, it would be better if the build kicked off from a specific project within the solution I had selected. However, I'm in a pretty good position right now, I just need to tweak some stuff. When the build fails, a new bug is created, and if you have email alerts setup, you will be notified.
Issues Resolved:
- Limit the amount of source downloaded (don't download the entire tree starting at $/Project
I solved this, at least for now, by going back into the build definition, and editing the workspace mapping. I change the default from $/Project -> $(Source) to $/Project/Folder -> $(Source)\Folder. Not only will this limit the amount of source downloaded, it is also used to
There is a section in the TFSBuild.csproj file for specifying reference paths. This is very useful when you have those developers who always add a reference in a nonstandard location and break the build. It is specified in an item group property, as a child of the root <Project> element. In my file, it was inserted at the end. I am going to try to insert this into a .targets file that I can reference from multiple build files.
<ItemGroup>
<!-- ADDITIONAL REFERENCE PATH
The list of additional reference paths to use while resolving references. For example:
<AdditionalReferencePath Include="C:\MyFolder\" />
<AdditionalReferencePath Include="C:\MyFolder2\" />
-->
</ItemGroup>
- Get a specific version (label)
I should have realized this earlier, but without an option in the Queue Build GUI, my need for building a specific version from a label drops significantly. I wanted QA to be able to build a version from a label, as defined by the dev team, such that the dev team could move on and start developing and checking in without impacting QA. The only "supported" way to get a specific version is to override the CoreGet task (see Ref #8), which means QA would have to check out and modify the TFSBuild.csproj file.
Open Issues:
- Select a specific project in a solution to build from.
- Current work around, is to create a new solution, or modify the solution I've been using to unselect some problem projects.
Miscellaneous:
- Read on Buck's blog that you have to have an interactive session running on the build server to do automated UI tests. He has instructions on how to do this. (See Ref #5)
- Extending the TFSBuild.csproj file. You can define reusable .targets files, which are just MSBuild files, and then import them into the TFSBuild.csproj file using <Import Project="Path\FileName.targets"/>
- You can add tasks based on TF Build targets in either the TFSBuild.csproj file, or your imported .targets. (See Ref #2)
- You can do incremental builds by setting the SkipClean property to true (See Ref #3).
- The .rsp file that is created with the TFSBuild.csproj file is a file that is used to pass command line arguments to MSBuild (See Ref #7).
References:
- MSDN Documentation
- Customizable Team Foundation Build Targets
- How to: Customize the SolutionToBuild Item Group
- Buck Hodges Blog
- Buck's basic guide to Team Build 2008
- Incremental Builds
- MSBuild command line reference
- Get a specific version