Welcome to MSDN Blogs Sign in | Join | Help

There are two approaches for building binaries targeting .NET 1.1 and .NET 1.0 in TeamBuild.

 

Approach# 1

1.       Upgrade VS2003/VS2002 project files to VS2005 using VS2005 upgrade wizard.

2.       Install the msbuild toolkit from here. This toolkit can build msbuild based projects targeting .NET 1.1 and .NET 1.0. Thanks to Robert MCLaws and Jomo Fisher for building such a great toolkit.

3.       Locate the target files installed at %ProgramFiles%\MSBuild\Interscape\MSBuildToolkit

4.       Follow the steps mentioned in Jomo’s blog and update each solution file to target .NET 1.1 and .NET 1.0.

5.       Choose appropriate configuration (platform as '.NET 1.0' or '.NET 1.1') in team build type.

6.       Install this toolkit on build machine.

7.       Install .NET1.1 and .NET1.0 redist on build machine if they are already not installed.

8.       That’s it, kickoff the build!

 

You may notice that the build process picked up .NET 1.1/.NET1.0 version of compiler and referenced .NET binaries from buildlog.txt.

 

(Snippet from my build log file)

 

Project "d:\builddir2\TestProject\Approach1\Sources\TargetNET1.1\TargetNET11.sln" is building "d:\builddir2\TestProject\Approach1\Sources\TargetNET1.1\TargetNET1.1\TargetNET11.csproj" (default targets):

Target PrepareForBuild:

Creating directory "d:\builddir2\TestProject\Approach1\Binaries\.NET 1.1\Debug\".

Creating directory "obj\.NET 1.1\Debug\".

Target CoreCompile:

D:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\Csc.exe /noconfig /warn:4 /define:CODE_ANALYSIS;DEBUG;TRACE;NET11 /reference:D:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.Data.dll /reference:D:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.dll /reference:D:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.Xml.dll /debug+ /debug:full /optimize- /out:"obj\.NET 1.1\Debug\TargetNET1.1.exe" /target:exe Program.cs Properties\AssemblyInfo.cs

 

Another beauty is that you can choose to run code analysis also while building these versions. All you need to do is to enable code analysis for this build type J

 

(Snippet from my build log file)

 

Target RunCodeAnalysis:

Running Code Analysis...

D:\Program Files\Microsoft Visual Studio 8\Team Tools\Static Analysis Tools\FxCop\FxCopCmd.exe  /o:"d:\builddir2\TestProject\Approach1\Binaries\.NET 1.1\Debug\TargetNET1.1.exe.CodeAnalysisLog.xml" /f:"d:\builddir2\TestProject\Approach1\Binaries\.NET 1.1\Debug\TargetNET1.1.exe" /d:"D:\WINDOWS\Microsoft.NET\Framework\v1.1.4322" /r:D:\Program Files\Microsoft Visual Studio 8\Team Tools\Static Analysis Tools\FxCop\\rules

 

Approach# 2

In case you don’t have an option of upgrading the project files to VS2005, you will need to use devenv command line (devenv.com) of the particular version and build. This works well but one difficulty is: TeamBuild needs the project output redirected to one common output folder in order to upload to the release server later on, but you cannot override the output directory with devenv command line. So, you will need either to modify your project files to use one common output directory, or, you will need to know the output directories of individual projects and use them in TeamBuild script to copy separately.

 

In the below example, I’ve VS2003Application.sln that contains three projects i) VS2003Application.csproj ii) CSWindowsApp.csproj iii) VBApp.vbproj.

 

I’ve added the following simple script overriding AfterCompile target in my TfsBuild.proj.

 

<PropertyGroup>

<VS2003_Devenv>$(ProgramFiles)\Microsoft Visual Studio .NET 2003\Common7\IDE\devenv.com</VS2003_Devenv>

<VS2003_SolutionName>$(SolutionRoot)\vs2003\VS2003Application\VS2003Application.sln</VS2003_SolutionName>

<VS2003_Configuration>Debug</VS2003_Configuration>

</PropertyGroup>

 

<ItemGroup>

<VS2003_OutputFiles Include="$(SolutionRoot)\vs2003\VS2003Application\bin\$(VS2003_Configuration)\**\*.*"/>

<VS2003_OutputFiles Include="$(SolutionRoot)\vs2003\CSWindowsApp\bin\$(VS2003_Configuration)\**\*.*"/>

<VS2003_OutputFiles Include="$(SolutionRoot)\vs2003\VBApp\bin\**\*.*"/>

</ItemGroup>

 

<Target Name="AfterCompile">

<Exec Command="&quot;$(VS2003_Devenv)&quot; &quot;$(VS2003_SolutionName)&quot; /build $(VS2003_Configuration)"/>

 

<MakeDir

Directories="$(BinariesRoot)\$(VS2003_Configuration)"

Condition="!Exists('$(BinariesRoot)\$(VS2003_Configuration)')" />

 

<Copy

SourceFiles="@(VS2003_OutputFiles)"     

DestinationFiles="@(VS2003_OutputFiles->'$(BinariesRoot)\$(VS2003_Configuration)\%(RecursiveDir)%(Filename)%(Extension)')"

/>

</Target>

 

Couple of things to notice here:

  1. This assumes VS 2003 is installed on the build machine.
  2. I’m using devenv.com, not devenv.exe.

 

You can extend this to build any number of solutions and different configurations. And, this can be easily modified to target VS 2002. Hope, this will provide you a starting point. Let me know if you need any further help.

 

Namaste!

Performing incremental builds in TeamBuild is very straight forward. Here are some details on how to get it setup:

 

Create the build type that you would want to do incremental builds with and perform the first build. This will create the required workspace, and get all sources on the build machine.

 

Do the following simple changes to this build type before starting the next build:

 

1.       TeamBuild cleans intermediate build folder and sources folder in Clean target. You will need to skip this target since you want to keep these files intact for the next build. Set the property SkipClean to true to achieve this.

 

2.       TeamBuild deletes and recreates workspace to clean sync the sources. You will need to skip this target as well, to do incremental sync. Set the property SkipInitializeWorkspace to true to achieve this.

 

3.       Optional: by default, the Get task does a ‘force’ get. You can set the property ForceGet to false to do a normal Get.

 

So, this is what you will need to add in TfsBuild.proj:

 

<PropertyGroup>

<SkipClean>true</SkipClean>

<SkipInitializeWorkspace>true</SkipInitializeWorkspace>

<ForceGet>false</ForceGet>

</PropertyGroup>

 

Let me know if you run into any issues or need help in customizing this further.

 

Namaste!

We have been seeing a huge customer request on how to publish a website in TeamBuild build process. Below, I have attempted to detail what I did to get this to work. This should help you get started!

 

I started with the goal of creating a virtual directory on the build machine and copying the website content built by my build process to this virtual directory. To achieve this, I need to override the target AfterCompile and include CreateVirtualDirectory and Copy tasks. I found .NET SDC toolkit (GDN2[1].0.051004.000.zip) on gotdotnet portal that offers a powerful set of msbuild tasks for enterprise builds. It includes tasks to create and manage websites. I’ve downloaded this toolkit onto my machine and tried to find the minimal set of files that I need to create virtual directory. The task is called Microsoft.Sdc.Tasks.Web.WebSite.CreateVirtualDirectory defined in Microsoft.Sdc.Tasks.dll. I located this binary at GDN2[1].0.051004.000\Microsoft.Sdc.Tasks\MainTempGDN\Install\bin.

 

Now, I’ve added the following script to my TfsBuild.proj:

 

<PropertyGroup>

<WebDeployFolder>d:\StagingFolder</WebDeployFolder>

<WebSiteSrcName>WebSite1</WebSiteSrcName>

<WebDeployName>WebSite1</WebDeployName>

<WebSitePreCompiledSrcFolder>$(SolutionRoot)\..\Binaries\.NET\Debug\_PublishedWebSites\$(WebSiteSrcName)</WebSitePreCompiledSrcFolder>

</PropertyGroup>

 

<UsingTask TaskName="Microsoft.Sdc.Tasks.Web.WebSite.CreateVirtualDirectory" AssemblyFile="Microsoft.Sdc.Tasks.dll" />

 

<Target Name="AfterCompile">

<MakeDir Directories="$(WebDeployFolder)\$(WebDeployName)" />

<CreateVirtualDirectory VirtualDirectoryName="$(WebDeployName)" Path="$(WebDeployFolder)\$(WebDeployName)" />

<Exec Command="xcopy /y /e $(WebSitePreCompiledSrcFolder) $(WebDeployFolder)\$(WebDeployName)"/>

</Target>

 

I know that TeamBuild process compiles web sites to binaries location and I’ve selected Debug|.NET flavor to build. This is what WebSitePreCompiledSrcFolder is pointing to. All other properties are self explanatory. This script creates a staging folder, create a virtual directory under web site “Default Web Site” on my build machine pointing to this staging folder and copies my precompiled web site to this staging folder.

 

I then checked in TfsBuild.proj and Microsoft.Sdc.Tasks.dll and its dependent binary Microsoft.Sdc.Configuration.dll into my build type folder ($/<TeamProject>/TeamBuildTypes/<BuildType>) and kicked off a build!

 

You might also encounter the following error that I had seen:

 

error MSB4062: The "Microsoft.Sdc.Tasks.Web.WebSite.CreateVirtualDirectory" task could not be loaded from the assembly d:\builddir\ScoutingTest\BuildTypeForWeb\BuildType\Microsoft.Sdc.Tasks.dll. Could not load file or assembly 'Microsoft.Sdc.Configuration, Version=1.2.5000.0, Culture=neutral, PublicKeyToken=e24a7ed7109b7e39' or one of its dependencies. Strong name validation failed. (Exception from HRESULT: 0x8013141A) Confirm that the <UsingTask> declaration is correct, and that the assembly and all its dependencies are available.

 

Seems like, they have missed signing this binary. I had to register this binary to my ‘skip verification’ list on my build machine (open .NET SDK command prompt and run “sn –Vr Microsoft.Sdc.Configuration.dll”) to get this to work.

 

Another thing to note is, the TeamBuild service account (the account with which the TeamBuild service is running) needs administrator access on the machine where the virtual directory is created. You will see an error similiar to below in case it was not administrator:

MSBUILD : warning : A task error has occured.

MSBUILD : warning : Message = Unknown error (0x80005000)

MSBUILD : warning : VirtualDirectoryName = mydemosite

MSBUILD : warning : Path = c:\Publish\mywebsite

MSBUILD : warning : MachineName = mymachine

MSBUILD : warning : WebSiteName = mydemosite

MSBUILD : warning : AppPoolId = DefaultAppPool

MSBUILD : warning : AppCreate = False

MSBUILD : warning : AnonymousUserName = <String.Empty>

MSBUILD : warning : AnonymousUserPassword = <String.Empty>

MSBUILD : warning : UncUserName = <String.Empty>

MSBUILD : warning : UncPassword = <String.Empty>

MSBUILD : warning : AuthFlags = <String.Empty>

MSBUILD : warning : AccessFlags = <String.Empty>

MSBUILD : warning :

MSBUILD : warning : at System.DirectoryServices.DirectoryEntry.Bind(Boolean throwIfFail)

MSBUILD : warning : at System.DirectoryServices.DirectoryEntry.Bind()

MSBUILD : warning : at System.DirectoryServices.DirectoryEntry.get_IsContainer()

MSBUILD : warning : at System.DirectoryServices.DirectoryEntries.ChildEnumerator..ctor(DirectoryEntry container)

MSBUILD : warning : at System.DirectoryServices.DirectoryEntries.GetEnumerator()

MSBUILD : warning : at Microsoft.Sdc.Configuration.Web.WebSite.GetIdentifierFromDescription(String machineName, String description)

MSBUILD : warning : at Microsoft.Sdc.Configuration.Web.WebSite.Load(String machineName, String description)

MSBUILD : warning : at Microsoft.Sdc.Tasks.Web.WebSite.CreateVirtualDirectory.InternalExecute()

MSBUILD : warning : at Microsoft.Sdc.Tasks.TaskBase.Execute()

 

It was not administrator in my case. So, I had to grant these permissions and restart TeamBuild service.

 

After completing these changes, my build process started creating a virtual directory and copying my newly build web site content to this folder. Yaahoo, I can now hit this website through my web testsJ

 

Let us examine the CreateVirtualDirectory in detail:

 

<CreateVirtualDriectory

VirtualDirectoryName="virtualDirectoryName"

Path="path"

MachineName="machineName"

AppPoolID="appPoolID"

AppCreate="appCreate"

WebSiteName="webSiteName"

AnonymousUserName="anonymousUserName"

AnonymousUserPassword="anonymousUserPassword"

UncUserName="uncUserName"

UncPassword="uncPassword"

AuthFlags="authenticationFlags"

AccessFlags="accessFlags"

/>

 

As you may have noticed, you can opt for a remote machine, point to any web site, point to an UNC share etc. This is a powerful task!

 

There are a bunch of useful tasks in Microsoft.Sdc.Tasks.Web namespace hierarchy. You can manage websites, ftp sites, and app pools etc pretty much do everything in web management.

 

Namaste!

TeamBuild implemented ‘Get’ task for syncing sources. This task is same as ‘tf get’, the command line utility to sync sources.

 

Properties Supported by Get Task

Workspace

The workspace used to get sources

Version

You can specify a version by:

  • Date/time (D10/20/2005)
  • Changeset version (C1256)
  • Label (Lmylabel)
  • Latest version (T)
  • Workspace version (Wworkspacename;owner)
  • If no version is provided, Team Build retrieves the latest server version of the specified filespec into your workspace.

by default, it is ‘T’, get latest sources.

FileSpec

items that need to be fetched. It is ‘*’, by default

Recursive

Recursively retrieves all items that match your filespec

Force

Overwrite files

 

The default build type uses this task to get the latest sources. However, you can very easily customize Get task to sync what you want. To do this, you will need to override the CoreGet target implemented in TeamBuild targets file Microsoft.TeamFoundation.Build.targets. I typically copy a target that I want to override into TfsBuild.proj of my build type and make changes appropriately. In this case, I copied CoreGet target into my TfsBuild.proj and played with it. I’m providing some examples below. This is a very powerful task. You can use the options Version and FileSpec in conjuction to get any sources of any version.

 

Getting Labled Sources

The following example gets the sources labeled with “Beta1” and builds.

 

<Target Name="CoreGet"

Condition=" '$(IsDesktopBuild)'!='true' "

DependsOnTargets="$(CoreGetDependsOn)" >

 

<Get

Condition=" '$(SkipGet)'!='true' "

Workspace="$(WorkspaceName)"

Recursive="$(RecursiveGet)"

Version="LBeta1"

Force="$(ForceGet)" />

 

<!-- Label all files in the workspace to identify sources used in this build -->

<Label

Condition=" '$(SkipLabel)'!='true' "

Workspace="$(WorkspaceName)"

Name="$(BuildNumber)"

Version="W$(WorkspaceName)"

Files="$/$(TeamProject)"

Recursive="true" />

 

</Target>

 

Getting a Particular Changeset into TeamBuild

The following example gets the sources labeled with “Beta1” and gets Porgram.cs that was checked in with changeset 26.

 

<Target Name="CoreGet"

Condition=" '$(IsDesktopBuild)'!='true' "

DependsOnTargets="$(CoreGetDependsOn)" >

 

<Get

Condition=" '$(SkipGet)'!='true' "

Workspace="$(WorkspaceName)"

Recursive="$(RecursiveGet)"

Version="LBeta1"

Force="$(ForceGet)" />

 

<Get

Condition=" '$(SkipGet)'!='true' "

FileSpec="$/ScoutingTest/HelloWorld/Program.cs"

Workspace="$(WorkspaceName)"

Recursive="$(RecursiveGet)"

Version="C26" />

 

<!-- Label all files in the workspace to identify sources used in this build -->

<Label

Condition=" '$(SkipLabel)'!='true' "

Workspace="$(WorkspaceName)"

Name="$(BuildNumber)"

Version="W$(WorkspaceName)"

Files="$/$(TeamProject)"

Recursive="true" />

 

</Target>

 

 

Namaste!

Few weeks ago, I worked with TSDT product team in setting up infrastructure for publishing test results into our TeamBuild dogfood server. This is one of the coolest features offered by TeamBuild and TSDT integration. The thought behind this feature was to allow testers to publish regression test results etc against a particular build. The build report includes all these test reports which would help the managers to gauge the quality of the build from one single source.

 

Walkthrough

1.       The user needs to get “Publish test results” permission on the team project as shown below. All contributors have this permission set in team projects created using ‘MSF Agile’ and ‘CMMI’ process templates.

 

 

2.       Open test results in Visual Studio to open them in “Test Results” window and click on the “Publish” button. This button is slightly undiscoverable, so I’m attaching a picture to help you.

 

3.       Select the “Associated build number” and “Build flavor”, select include code coverage data checkbox in case these runs have CC data and you want to publish them and click OK.

 

4.       You are done! The build report will now include this test report as well.

 

Here are some details how this is internally implemented and the permissions required on the build drop share. IMO, these are important to know so that users inadvertently don’t give additional permissions which might compromise the security. Read on…

 

How does publishing work from client?

1.       Visual Studio client (the publishing client) sends a publish request to the Team Foundation Server publishing web service

2.       The publishing web service authenticates the user against ‘Publish Test Results’ permission

3.       It then creates an appropriate testresults folder under the build drop location and gives NTFS full control access to the publishing client

4.       The publishing client copies the test results to the drop location

5.       Once the copying is done, the publishing web service revokes the NTFS permissions that were granted before.

 

Permissions required on the build drop share

The users need to be granted ‘Full Control’ at share permission level.

 

This is required for (4) above to work. Even though the user has been granted full control, the non-read access for individual users can be controlled using NTFS permissions as described below. IMO, the recommended permissions are:

 

1.       Unselect ‘Allow inheritable permissions from the parent…’ so that this folder does not inherit permissions from its parent folder (select properties of the folder à select Security Tab à click on “Advanced” button) as shown below.

 

2.       Remove all permissions granted to <Machine>\Users (by default all authenticated users are part of this group). Give ‘Read’ permission only (for e.g., a default folder will have the highlighted permissions set which will need to be removed) as shown below.

 

Namaste!

There are few things to note while evaluating ASP.NET projects under TeamBuild. We had several instances of our customers selecting ‘Any CPU’ configuration while building default ASP.NET web projects. By ‘default’ I mean, an ASP.NET project that is created choosing default options in VS. Note that, the default configuration enabled for a solution that contains only Web Projects is “.NET”. In case the solution contains non-web projects, for example a class library project, the default configuration will be “Mixed Platforms”. You will need to select configurations accordingly.

 

Next, you might see some build errors while building default ASP.NET projects in Teambuild. If you have seen errors something like below, you have hit a known issue that we won’t be able to fix in this version J

 

ASPNETCOMPILER(0,0): error 1003: The directory 'd:\builddir\MyTeamProject\SampleWS\WebSites\SampleWS\' doesn't exist.

 

This is because, when a web site is created using default options, VS saves solution files and website files in two different locations and unfortunately, it is not very explicit to the user. When I created a website project called SampleWS using default options, VS saved solution files at “D:\Documents and Settings\NAGARAJP\My Documents\Visual Studio 2005\Projects\SampleWS” and website folder at “D:\Documents and Settings\NAGARAJP\My Documents\Visual Studio 2005\Websites\SampleWS”. The solution file contains a relative pointer (PhysicalPath property in the solution file) to the web site folder to locate it for compilation. But, when this solution gets checked in, everything goes as one blob with .sln file at the root folder and all websites as immediate sub folders. Refer here for more details. This results in broken PhysicalPaths in the solution file. Since the build machine syncs as persisted on the source control, the solution won’t be able to locate these websites and results in compilation errors.

 

The best way to avoid this problem in the first place is to create a blank a solution, and create web sites at the same location where the solution is created.

 

Well, I didn’t know this and hit this issue now. Is there any way to fix it?

Yes. You will have to hand edit the solution file to modify the properties Debug.AspNetCompiler.PhysicalPath and Release.AspNetCompiler.PhysicalPath to point to the website folder as in source control and check it in back. In my sample, these were pointing to "..\..\WebSites\SampleWS\". I changed them to “SampleWS\" to make them inline with what is there on source control. It will be similar for you also.

 

Now, it is obvious that, on the local machine, you won’t be able to load this solution in VS as well as do msbuild command line compilation. You can do the following simple tweaks to the local workspace and get it to work. Here is what I did:

 

-          In my example, I’ve two mappings like below (you will have similar mappings)

a.     $/MyTeamProject/SampleWS: D:\Documents and Settings\NAGARAJP\My Documents\Visual Studio 2005\Projects\SampleWS

b.     $/MyTeamProject/SampleWS/SampleWS: D:\Documents and Settings\NAGARAJP\My Documents\Visual Studio 2005\WebSites\SampleWS

-          I checked in all changes from my website folder D:\Documents and Settings\NAGARAJP\My Documents\Visual Studio 2005\WebSites\SampleWS

-          I ran ‘tf workspace’ command from D:\Documents and Settings\NAGARAJP\My Documents\Visual Studio 2005\Projects\SampleWS and removed the mapping “D:\Documents and Settings\NAGARAJP\My Documents\Visual Studio 2005\WebSites\SampleWS” so that everything under $/MyTeamProject/SampleWS include the SampleWS web project folder will be synced to D:\Documents and Settings\NAGARAJP\My Documents\Visual Studio 2005\Projects\SampleWS

-          Then, I ran ‘tf get /r *’ to sync the web site folder to the new location

-          Now I have two copies of website folder, one under solution folder and one originally created at D:\Documents and Settings\NAGARAJP\My Documents\Visual Studio 2005\WebSites\SampleWS, so I removed the original one to avoid confusion

-          I deleted .suo file (note that this is a hidden file) from the solution folder so that it does not use any cached information and opened SampleWS.sln in VS.

-          Boom, everything is up and working!!

 

Namaste!

Currently, TeamBuild does not have out of the box support to create workitems for test failures. I’ve attempted put some details below since this is a common request for several of our customers. It might look complicated if you are going to skim through this blog. But, I promise it is fairly straight forward :)  Read on...

 

The targets that are executed in a full stack TeamBuild are defined at %ProgramFiles%\MSBuild\Microsoft\VisualStudio\v8.0\TeamBuild\Microsoft.TeamFoundation.Build.targets. The target RunTestWithConfiguration is responsible for running tests.

 

The definition of this target is as follows:

 

<Target Name="RunTestWithConfiguration" >

 

    <TeamBuildMessage

          Tag="Configuration"

          Condition=" '$(IsDesktopBuild)'!='true' "

          Value="$(Flavor)" />

 

 

    <!-- Test task for the end-to-end build -->

    <TestToolsTask

          Condition=" '$(IsDesktopBuild)'!='true' and '%(MetaDataFile.Identity)'!=''"

          BuildFlavor="$(Flavor)"

          Platform="$(Platform)"

          PublishServer="$(TeamFoundationServerUrl)"

          PublishBuild="$(BuildNumber)"

          SearchPathRoot="$(SearchPathRoot)"

          PathToResultsFilesRoot="$(TestResultsRoot)"

          MetaDataFile="%(MetaDataFile.Identity)"

          RunConfigFile="$(RunConfigFile)"

          TestLists="%(MetaDataFile.TestList)"

          TeamProject="$(TeamProject)"

  ContinueOnError="true" />

 

    <!-- Test task for the desktop build -->

    <TestToolsTask

          Condition=" '$(IsDesktopBuild)'!='false' and '%(MetaDataFile.Identity)'!=''"

          SearchPathRoot="$(SearchPathRoot)"

          PathToResultsFilesRoot="$(TestResultsRoot)"

          MetaDataFile="%(MetaDataFile.Identity)"

          RunConfigFile="$(RunConfigFile)"

          TestLists="%(MetaDataFile.TestList)"

          ContinueOnError="true" />

 

  </Target>

 

If you notice the highlighted part, ContinueOnError is set to true for the task TestToolsTask to ignore the test failures and continue the build process. We need to replace this with a new target and call it where there is an error in the target. MSBuild supports an element called OnError to achieve this behavior. Here is the new code after ContinueOnError is removed and OnError is added:

 

<Target Name="RunTestWithConfiguration" >

 

    <TeamBuildMessage

          Tag="Configuration"

          Condition=" '$(IsDesktopBuild)'!='true' "

          Value="$(Flavor)" />

 

 

    <!-- Test task for the end-to-end build -->

    <TestToolsTask

          Condition=" '$(IsDesktopBuild)'!='true' and '%(MetaDataFile.Identity)'!=''"

          BuildFlavor="$(Flavor)"

          Platform="$(Platform)"

          PublishServer="$(TeamFoundationServerUrl)"

          PublishBuild="$(BuildNumber)"

          SearchPathRoot="$(SearchPathRoot)"

          PathToResultsFilesRoot="$(TestResultsRoot)"

          MetaDataFile="%(MetaDataFile.Identity)"

          RunConfigFile="$(RunConfigFile)"

          TestLists="%(MetaDataFile.TestList)"

          TeamProject="$(TeamProject)"

 />

 

    <!-- Test task for the desktop build -->

    <TestToolsTask

          Condition=" '$(IsDesktopBuild)'!='false' and '%(MetaDataFile.Identity)'!=''"

          SearchPathRoot="$(SearchPathRoot)"

          PathToResultsFilesRoot="$(TestResultsRoot)"

          MetaDataFile="%(MetaDataFile.Identity)"

          RunConfigFile="$(RunConfigFile)"

          TestLists="%(MetaDataFile.TestList)"

          ContinueOnError="true" />

 

  <OnError ExecuteTargets="OnTestFailure;" />

  </Target>

 

Note that I haven’t removed ContinueOnError for test task that runs for desktop build, because I don’t want to create bugs for test failures that happen in desktop build.

 

Now, we need to define OnTestFailure target. There is a task called CreateNewWorkitem available in TeamBuild to create workitems. I’ve used that here. Here is the target definition:

 

<Target Name="OnTestFailure">

   

    <CreateProperty Value="Work Item created by Team Build on BVT failure. " >

      <Output TaskParameter="Value" PropertyName="DescriptionText" />

    </CreateProperty>

 

    <CreateProperty Value="Build log is at

        &lt;a

        href='file:///$(DropLocation)\$(BuildNumber)\BuildLog.txt'

        &gt;

        $(DropLocation)\$(BuildNumber)\BuildLog.txt

        &lt;/a &gt;.

      ">

      <Output TaskParameter="Value" PropertyName="BuildlogFile" />

    </CreateProperty>

 

    <CreateProperty Value="Test Results are at

        &lt;a

        href='file:///$(DropLocation)\$(BuildNumber)\TestResults'

        &gt;

        $(DropLocation)\$(BuildNumber)\TestResults

        &lt;/a &gt;.

      ">

      <Output TaskParameter="Value"

              PropertyName="TestResultsFolder"

              Condition="Exists('$(DropLocation)\$(BuildNumber)\TestResults')" />

    </CreateProperty>

   

    <CreateNewWorkItem

          BuildId="$(BuildNumber)"

          Description="Tests are failed. $(BuildlogFile) $(TestResultsFolder)"

          TeamProject="$(TeamProject)"

          TeamFoundationServerUrl="$(TeamFoundationServerUrl)"

          Title="BVT failures in build $(BuildNumber)"

          WorkItemFieldValues="$(WorkItemFieldValues)"

          WorkItemType="$(WorkItemType)"

          ContinueOnError="true" />

   

  </Target>

 

I’m creating a new workitem with title as “BVT failures in <build number>” and adding information about the build log file and test results folder in the description. I’m using the same workitem fields specified for build failures. You can find this property in TfsBuild.proj.

 

Now, I need to bring all these things together. To achieve this, I copied the target RunTestWithConfiguration from Microsoft.TeamFoundation.Build.targets and added to TfsBuild.proj, so that this version of the target is called in the build process. Now, I made the changes described above to this newly added target. After this, I added the target OnTestFailure as defined above. This is how it looked with all these changes:

 

<!--

I’ve pulled the target RunTestWithConfiguration (this is responsible for running tests) from

Microsoft.TeamFoundation.Build.targets into TfsBuild.proj and hooked in a new target called

OnTestFailure to create a workitem when there is a test failure. The changes I made are highlighted in bold.

  -->

 

  <Target Name="RunTestWithConfiguration" >

 

    <TeamBuildMessage

          Tag="Configuration"

          Condition=" '$(IsDesktopBuild)'!='true' "

          Value="$(Flavor)" />

 

    <TeamBuildMessage

          Tag="Platform"

          Condition=" '$(IsDesktopBuild)'!='true' "

          Value="$(Platform)" />

 

    <!-- SearchPathRoot for not Any CPU -->

    <CreateProperty

          Condition=" '$(Platform)'!='Any CPU' "

          Value="$(BinariesRoot)\$(Platform)\$(Flavor)\" >

      <Output TaskParameter="Value" PropertyName="SearchPathRoot" />

    </CreateProperty>

 

    <!-- SearchPathRoot for Any CPU -->

    <CreateProperty

          Condition=" '$(Platform)'=='Any CPU' "

          Value="$(BinariesRoot)\$(Flavor)\" >

      <Output TaskParameter="Value" PropertyName="SearchPathRoot" />

    </CreateProperty>

 

    <!-- Test task for the end-to-end build -->

    <!-- New: Remove ContinueOnError=true so that OnError target defined below can be called when there is a failure -->

    <TestToolsTask

          Condition=" '$(IsDesktopBuild)'!='true' and '%(MetaDataFile.Identity)'!=''"

          BuildFlavor="$(Flavor)"

          Platform="$(Platform)"

          PublishServer="$(TeamFoundationServerUrl)"

          PublishBuild="$(BuildNumber)"

          SearchPathRoot="$(SearchPathRoot)"

          PathToResultsFilesRoot="$(TestResultsRoot)"

          MetaDataFile="%(MetaDataFile.Identity)"

          RunConfigFile="$(RunConfigFile)"

          TestLists="%(MetaDataFile.TestList)"

          TeamProject="$(TeamProject)"

          />

 

    <!-- Test task for the desktop build -->

    <TestToolsTask

          Condition=" '$(IsDesktopBuild)'!='false' and '%(MetaDataFile.Identity)'!=''"

          SearchPathRoot="$(SearchPathRoot)"

          PathToResultsFilesRoot="$(TestResultsRoot)"

          MetaDataFile="%(MetaDataFile.Identity)"

          RunConfigFile="$(RunConfigFile)"

          TestLists="%(MetaDataFile.TestList)"

          ContinueOnError="true" />

 

    <!--Execute OnTestFailure target when there is a test failure from end-to-end build -->

   

    <OnError ExecuteTargets="OnTestFailure;" />

  </Target>

 

  <!--

    New: OnTestFauilre target definition

  -->

  <Target Name="OnTestFailure">

   

    <CreateProperty Value="Work Item created by Team Build on BVT failure. " >

      <Output TaskParameter="Value" PropertyName="DescriptionText" />

    </CreateProperty>

 

    <CreateProperty Value="Build log is at

        &lt;a

        href='file:///$(DropLocation)\$(BuildNumber)\BuildLog.txt'

        &gt;

        $(DropLocation)\$(BuildNumber)\BuildLog.txt

        &lt;/a &gt;.

      ">

      <Output TaskParameter="Value" PropertyName="BuildlogFile" />

    </CreateProperty>

 

    <CreateProperty Value="Test Results are at

        &lt;a

        href='file:///$(DropLocation)\$(BuildNumber)\TestResults'

        &gt;

        $(DropLocation)\$(BuildNumber)\TestResults

        &lt;/a &gt;.

      ">

      <Output TaskParameter="Value"

              PropertyName="TestResultsFolder"

              Condition="Exists('$(DropLocation)\$(BuildNumber)\TestResults')" />

    </CreateProperty>

   

    <CreateNewWorkItem

          BuildId="$(BuildNumber)"

          Description="Tests are failed. $(BuildlogFile) $(TestResultsFolder)"

          TeamProject="$(TeamProject)"

          TeamFoundationServerUrl="$(TeamFoundationServerUrl)"

          Title="BVT failure in build $(BuildNumber)"

          WorkItemFieldValues="$(WorkItemFieldValues)"

          WorkItemType="$(WorkItemType)"

          ContinueOnError="true" />

   

  </Target>

 

One of the enhancements in C++ compiler space for Whidbey is building Profile-Guided Optimized (PGO) builds. Profile-guided optimization lets you optimize an output file, where the optimizer uses data from test runs of the .exe or .dll file. The data represents how the program is likely to perform in a production environment. Please refer to http://msdn2.microsoft.com/en-us/library/e7k32f4k for more details.

 

This is applicable only for Release configuration. There are three phases in generating PGO builds:

1.       Instrumentation (PGI) Phase: First, the user instruments the build through PG Instrumentation (using Build à Profile Guided Optimization à Instrument) which generates the .exe and .pgd files.

2.       Training App: The user then trains the app by running it through the common user scenarios which generates test data, .pgc files (either run the app directly through command line and run it through Build à Profile Guided Optimization à Run Instrumented/Optimized Application).

3.       Optimization Phase: At this stage, both .pgd and .pgc files should be available at $(outdir). There are two options to do this:

-          Optimization (PGO) Option: The user then builds an optimized image by linking the object files in conjunction with the test data which is called Optimization (Build à Profile Guided Optimization à Optimize). One important thing to note is any changes to the sources after building the instrumented application and the .pgd file can dramatically affect PGO code generation and optimization decisions. So, while doing Optimize, the linker performs some checks to make sure that no changes happened to the input files (object files, libraries, etc…) used to build the instrumented application.

-          Update (PGU) Option: There is another option available to create optimized binary called Update. Let us say, user discovers that he forgot to update the version number of the application, or, discovered a trivial bug which needs a very tiny fix that does not dramatically affect the flow in the application. He can use this option. Using this option the linker will not perform the checks it does when using Optimize option. The user can edit and recompile files or even add new files to the application between PGI and PGU builds.

 

Since these options are available through C++ compiler, user can use them through command line as well. Please refer http://msdn2.microsoft.com/en-us/library/xct6db7f(en-us,vs.80).aspx for a detailed walkthrough.

 

How does this work under TeamBuild?

We need to create two configurations for instrumentation and optimization and enable them in the teambuild process as below:

 

  1. Create two configurations POGO instrumentation and Optimization let’s say PGIRelease and PGORelease with the following properties set:

PGIRelease à Configuration Properties à General à Whole Program Optimization

Profile Guided Optimization - Instrument

PGIRelease à Configuration Properties à Linker à Optimization à Link Time Code Generation

Profile Guided Optimization - Instrument (/ltcg:pginstrument)

PGORelease à Configuration Properties à General à Whole Program Optimization

Profile Guided Optimization - Optimize

PGORelease à Configuration Properties à General à Intermediate Directory

PGIRelease

PGORelease à Configuration Properties à Linker à Optimization à Profile Guided Database

$(SolutionDir)PGIRelease\$(TargetName).pgd

PGORelease à Configuration Properties à Linker à Optimization à Link Time Code Generation

Profile Guided Optimization - Optimize (/ltcg:pgoptimize)

 

  1. Create a build type with PGIRelease configuration selected
  2. Create a copy of vcoverrides.vsprops, call it PGOOverrides.vsprops and set the following properties:

  <Tool Name="VCLinkerTool" ProfileGuidedDatabase="$(BinariesRoot)\Win32\PGIRelease\$(TargetName).pgd" />

  1. Override the AfterCompile target with the following:
    1. Run tests against the exe generated from PGIRelease configuration to generate .pgc files
    2. Add an msbuild task to compile PGORelease configuration

 

An example of this in Tfsbuild.proj would be something like this:

<Target Name="AfterCompile">

    <Exec Command="$(BinariesRoot)\win32\PGIRelease\PGODemo.exe" />

    <MSBuild

Projects="@(SolutionToBuild)" Properties="Configuration=PGORelease;Platform=Win32;SkipInvalidConfigurations=true;VCBuildOverride=$(MSBuildProjectDirectory)\PGOOverrides.vsprops;FxCopDir=$(FxCopDir);OutDir=$(OutDir);ReferencePath=$(ReferencePath);TeamBuildConstants=$(TeamBuildConstants);$(CodeAnalysisOption)"

      Targets="Build" />

</Target>

Note: currently, there is some problem with running instrumented binaries through a service. Amit is following up on that. Until this is resolved, the tests need to be run manually. To validate this, we’ve replaced the exec task with a waiter task to halt the build process, ran the exe on the build machine and resumed the build process. Everything worked fine.

  1. Kick off the build. The optimized binaries will be dropped at win32\PGORelease location and instrumented binaries at win32\PGIRelease location.

1.      We have now included a command line utility to manage builds. It is called TfsBuild.exe can be located at %ProgramFiles%\Microsoft Visual Studio 8\Common7\IDE. It is available in Build Machine SKU and Team Foundation Client SKU. Here is the screenshot of the tool.

 

2.      One of our customer top requests was to enable continuous integration through TeamBuild. We are putting up a white paper and a sample to explain this. It should be on msdn very soon.

 

3.      We have made several significant improvements with P2P references. Users can now use P2P references between unmanaged projects, managed à unmanaged and vice versa. Unfortunately, these fixes could not make into PDC build (50727.26), so users will need to wait for Visual Studio 2005 RTM version. We have also fixed a good number of bugs with ASP.NET web projects references. These should be available in PDC bits itself.

 

4.      We have fixed significant number of issues with Test integration.

 

TeamBuild now offers almost every feature that is in Team System Testing Tools. Some of noteworthy features are:

a.       Enabling code coverage.

b.      ASP.NET Unit Tests

c.       Remote test execution

 

And some of TeamBuild specific improvements include:

a.       Running tests from desktop build

b.      Deleting test results from build reports

c.       Better presentation of test results in build reports

d.      Customization of build type to include multiple test metadata files and test lists

 

Note: The user will need to install Team System Testing Tools (VSTT, VSTD or VSTS) on the build machine to enable this feature.

 

5.      We have enhanced TeamBuild web services for users to push external build data into TeamBuild opstore. These are Add* and Update* web methods in BuildStore.asmx. Users should be able to integrate 3rd party build processes into TeamBuild through this feature.

 

6.      The build report has been completely revamped for much better presentation:

 

 

7.      We have made fixes to build machine to accept requests only from legitimate Team Foundation Servers to tighten from security aspect. The build machine now ties up with one Team Foundation Server at any time. The user may redirect to a different server by changing HKCU\Software\Microsoft\VisualStudio\8.0\TeamBuild\AllowedTeamServerof the TeamBuild service account on the build machine.

 

Recently, I had an opportunity to answer couple of customer questions on building web sites with references under TeamBuild. Here are the details:

 

If the user is using project-to-project (P2P) reference approach to reference a project in ASP.NET project, then he should not checkin the binaries related to dependent project in the bin folder of ASP.NET project. When there is a P2P reference, the project dependency order is automatically set and the dependent dll will be copied to the bin folder after it is built.

 

In case the user is using hard coded reference (by browsing to the file), we should recommend the following:

  1. Checkin the external references under the same TeamProject.
  2. Create a workspace with a mapping to the common root of the solution folder and the external references folder. For example, the common root of a solution that is checked in at $/TeamProject/Foo/Bar/Solution and the external references that are checked in at $/TeamProject/Foo/ExternalReferences is anything above Foo.
  3. Get all files using this workspace and adjust the references by browsing to the checked in external references
  4. Select a workspace that includes both external references folder and solution folder in the Team Build type

Finally, I’m getting there! I’ve been reading blogs of my friends and esteemed colleagues and I’m excited about them. It is definitely a great way of sharing thoughts, emotions and connecting people. I’ve been reading an article on how to write for living web. Few points inspired me – write for a reason, make good friends and relaxJ

 

Well, I’ll keep my introduction short. I’m Nagaraju Palla, born and brought up in a small town in southern part of India. Friends call me Nagaraj, NP and Palla. I’m living with my beautiful wife Sujatha and two wonderful kids, Praneeth 7 years and Laasya 2 years. It is a great fun being a fatherJ I work for Microsoft India Development Center out of Redmond, USA. It is challenging job, being a liaison between India and Redmond teams for our product group. I’ve some interesting experiences from my job role which I hope to share with you soon.

 

It is great to see our product leadership team encouraging our group to get connected with customers with blogs, being responsive in product newsgroups and helping our customers from all possible avenues. I’m super excited about this. About my role – I’m QA lead in a group working on Visual Studio Team Foundation. Our group owns TeamBuild and migration tools. One of the things I like and feel good about this group is that people are smart, excited about what they are doing and have fun at work. I hope to share some of these experiences as well.

 

Our group shipped Beta3 last week and there is a great excitement seen in our customers from that. I want to see this momentum to continue and this product to win the hearts of our customers.

More Posts « Previous page
 
Page view tracker