Patrick Carnahan, a developer on Team Build, put together the following guide to the basic, as well as a few advanced, features of Team Build in TFS 2008. It's a great way to get started with continuous integration and other features in TFS 2008.
Team Build – Continuous Integration
One of the new and most compelling features of Team Foundation Build is the out-of-the-box support for continuous integration and scheduling. A few in-house approaches have been built around the TFS Soap Event mechanism, most likely set to listen for check-in events and evaluating whether or not a build should be performed. The disadvantages to this approach are the speed and accuracy at which build decisions may be made.
For all of the following steps, it is assumed that the ‘Edit Build Definition’ dialog is currently active. To activate this dialog, expand the ‘Builds’ node of the team project to which your V1 build type belongs (or to which you want to add a new V2 build definition) and click on ‘Edit Build Definition’ as shown below.
Setting up the workspace
Setting up a workspace is pretty important to the continuous integration build, since this is how the server determines when to automatically start builds on your behalf. Although the default workspace mapping is $/<Team Project Name> -> $(SourceDir), something more specific should be used in practice. For instance, in the Orcas PU branch you should use (at a minimum) the mapping $/Orcas/PU/TSADT -> $(SourceDir).
What is this $(SourceDir) variable? Well, in V1 the build directory was specified per build type, meaning that the build type was built on the same directory no matter what machine the build was performed on. In V2 we have separated out the idea of a build machine into a first-class citizen called a Build Agent; this is where the build directory is stored. The variable $(SourceDir) is actually a well-understood environment variable by Team Build, and is expanded to: <BuildAgent.BuildDirectory>\Sources (more on the Build Directory and environment variables later). Typically you will want to make use of $(SourceDir) and keep everything relative to it, but there is no restriction that forces this upon you.
Just so we’re on the same page with the workspace dialog, a picture has been included below. Those of you familiar with version control workspaces should feel right at home!
Already have a workspace ready to go? Simply select the ‘Copy Existing Workspace’ button to search for existing workspaces to use as a template. The local paths will be made relative to $(SourceDir) automatically!
Defining a Trigger
The trigger defines how the server should automatically start builds for a given build definition.
The first option should be self-explanatory, and keeps the build system behaving just like V1 (no automatic builds). The other options are as follows.
- The 'Build each check-in' option queues a new build for each changeset that includes one or more items which are mapped in a build definition's workspace.
- 'Accumulate check-ins', otherwise known as 'Rolling Build', will keep track of any checkins which need to be built but will not start another build inside of the defined quiet period. This option is a good way to control the number of builds if continuous integration is desired but you want a maximum number of builds per day (e.g. 12 builds per day, which would require a quiet period of 120 minutes) or your builds take much longer than the typical time between checkins.
- Standard scheduled builds will only occur if checkins were made since the previous build. Don't worry about this rule affecting the first build, however, because the system will ensure that the first build is started right on time.
- Scheduled builds can optionally be scheduled even if nothing changes. This is useful when builds are dependent on more than what is in version control.
One of the side effects of a continuous integration system is that a greater number of builds will be created. In order to manage the builds and drops created through CI we have introduced a feature in Team Build called drop management.
Drop management is enabled through a concept we call Retention Policy in Team Build, which allows you to define how many builds to retain for a particular build outcome. For instance, you may only want to keep the last 5 successful builds and only one of any other kind. Through retention policy you can define this by setting the appropriate values in the dialog shown above and the server will manage the automatic deletion of builds for you.
What if you don’t want a build to be susceptible to automatic deletion? We have an option available on individual builds if you would like to retain a build indefinitely (it just so turns out that this is what the menu option is called). To do this go to the ‘Build Explorer’ in Visual Studio 2008 (available by double clicking a node under the Builds node in the Team Explorer window), right click on the build, then select ‘Retain Indefinitely’. Once this option has been toggled on you will see a padlock icon next to the build.
If you decide that the build is no longer useful, simply toggle the option off for the build and let drop management take care of the build automatically.
1. Automated UI Tests
Automated UI tests cannot be run in the build agent running as a windows service since it is not interactive, meaning that it cannot interact with the desktop. So, we have provided the ability to run an interactive instance of the service out-of-the-box!
The first thing you will need to do is create a new build agent on the server. To do this you should right click on the ‘Builds’ node for your team project, then click ‘Manage Build Agents’. Once this dialog comes up, click the ‘Add’ button which will bring you to the dialog below.
The display name can be anything descriptive you want. For instance, if the machine name is ‘BuildMachine02’ you may choose to name the build agent ‘BuildMachine02 (Interactive)’ so you can easily differentiate between the interactive and non-interactive agents. The computer name should be the computer name of the machine on which the build service resides, and the port should be changed to 9192 since it is the default interactive port. When changing the port you may see a dialog with the message below, which may be safely disregarded in this case since you’ll be using the default interactive port.
TF226000: After you change the port that is used by Team Foundation Build, you must also update the build service on the build computer to use the new port. For more information, see http://go.microsoft.com/fwlink/?LinkId=83362 .
In order to run the build service in interactive mode just start a command-prompt on the build computer in the directory %PROGRAMFILES%\Microsoft Visual Studio 9.0\Common7\IDE\PrivateAssemblies (if you do not want to run the build agent service as yourself then you need to be sure to spawn the command-prompt as the correct user using the ‘runas’ command). Now that you’re in the directory as the appropriate user all you need to do is type ‘TFSBuildService.exe’, which will output something similar to the following:
C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\PrivateAssemblies>TFSBuildService.exe
Press the Escape key (Esc) to exit...
Once you see that prompt your interactive agent is ready to go. You’ll need to leave that command running. Be sure that any time you need to run automated UI tests that you target the correct agent!
2. Build Directory Customization
In TFS 2005, you were able to specify the root build directory which should be used in the build type definition file TfsBuild.proj. During the build, the root build directory would automatically get expanded to:
<Root Build Directory>\<Team Project Name>\<Build Type Name>
This was not configurable and was done this way to ensure uniqueness across build types being built on the same machine. The sources, binaries, and build type were then brought into sub folders named ‘Sources’, ‘Binaries’, and ‘BuildType’, respectively. Since the names could get quite long, there were quite a few issues with path name length errors which were unavoidable.
In TFS 2008 we have made it easier to customize the build directory on the agent through the use of 2 well-known environment variables.
$(BuildDefinitionPath), which expands to <TeamProjectName>\<DefinitionName>
$(BuildDefinitionId), which is the unique identifier by which the definition may be referenced (an Int32)
The build directory is no longer guaranteed to be unique by the system automatically unless one of these two variables is used. This approach has some great advantages, especially since $(BuildDefinitionId) is merely an Int32 and will definitely reduce the length of paths at the build location!
There is another method by which this path may be reduced even more if the source control enlistment requires it. If you take a look at the file %PROGRAMFILES%\Microsoft Visual Studio 9.0\Common7\IDE\PrivateAssemblies\TfsBuildService.exe.config on the build computer, you will see some settings which may be of interest to you.
<add key="SourcesSubdirectory" value="Sources" />
<add key="BinariesSubdirectory" value="Binaries" />
<add key="TestResultsSubdirectory" value="TestResults" />
These control the name of the sub-directories which will house the Sources, Binaries, and TestResults. If you need an even shorter path, you could name the sources sub directory ‘s’!
NOTE: Be sure to restart the team build service ( the Windows service or the interactive service, as needed) after making changes to this file in order for the changes to take effect!
3. Port Configuration
For Orcas we have changed the communication method for the build agent (the build agent is the service installed and running on the build computer). In TFS 2005 the Team Build Server communicated with the build machines via .NET Remoting. In TFS 2008 we changed this to use SOAP+XML over HTTP, just like the other Team Foundation services. In order to do this, we have switched to using Windows Communication Foundation self-hosting functionality to expose the service end-point without requiring Internet Information Services (IIS) on the build computer. There is a new series of steps which must be followed in order to change the port for an existing TFS 2008 build agent.
- Disable the build agent on the server using the 'Manage Build Agents' option in Visual Studio 2008 described above. This will keep the server from starting new builds on the machine, but will let existing builds finish. This way you do not accidentally stop an in-progress build from finishing.
- Once there are no builds running, issue a 'Stop' command to the build Windows service, either using the Windows Services control panel or from the command line using the "net stop vstfbuild" command.
- Navigate a command prompt to the directory %PROGRAMFILES%\Microsoft Visual Studio 9.0\Common7\IDE\PrivateAssemblies.
- Open the file TFSBuildService.exe.config, and look for a child element in the <appSettings> section with the key="port" (case sensitive!). Change the value of that key to the desired port and remember the value for the next step.
- In the same directory there will be an executable named wcfhttpconfig.exe. This will ensure that the appropriate URL ACLs are in place to allow the service account to listen for incoming HTTP requests. The command you should issue is: 'wcfhttpconfig reserve <domain>\<user name> <port number>'. You must run this command as a local administrator.
- Now issue a 'Start' command to the window service.
- Change the status of the build agent back to 'Enabled' using the 'Build Agent Properties' dialog and click ok.
You can find the official docs on MSDN at How to: Configure an Interactive Port for Team Foundation Build.
NOTE: Changing the port of the Interactive Service is exactly the same as the instructions above with one exception: the appSettings key you will need to modify is ‘InteractivePort’.
[UPDATED 9/07/07] I've added links to the official docs on changing the port.