Trigger a CI build after a gated checkin

We want to trigger a CI build after a gated checkin because we have two builds in our company. One with a gated checkin for fast building and very important test. The other build is for code analysis and long running tests. Because we don’t want to wait very long on our CI build we have created that QM build. The problem is that the QM isn’t triggered anymore after changing the CI build to a Gated checkin build.

I found a blogpost for TFS 2010. Because TFS 2013 is slightly different, I thought I would give it an update.

This is how to fix it for TFS 2013

  1. Create an argument called “NoCIOption” of the type boolean with default True.
    CreateDisableCiArgument
  2. Set the metadata information so you understand the argument in your build definition.
    MetadataDisableCiBuild
  3. Use the argument in the TFS 2013 build template. You can find the property under “Run on agent” and then “Get sources from Team Foundation Version Control”. Go to the properties window and change the hard coded “True” in the NoCIOption property to the argument you just created.
    SetDisableCiArgument

Now checkin your changes of the teamplate and use (if you don’t already have) the template in your CI build (the one with the gated checkin). Change the new argument to “false”.

Now your second build (our QM) is also triggered again.

TFS delete build definition timeout

When you do a tfs delete on a build definition and you receive a timeout, you probably have to many builds in your TFS server. Even if you delete all the build for your build definition, tfs still stores all the builds in your TFS Server. Just like your TFS Team projects, you have to delete and then destroy the builds. After that, you could delete the build definition completely.

The only way to do this is, is to delete and destroy the builds in pieces. You can only do that by the command prompt.

I created a PowerShell script that loops through the builds for a specific build definition and deletes all the builds before a specific date. So if your build is maybe a year old, you could start the script a year back from now and loop through all the builds until let’s say two months ago. You could skip the number of days you want. I set the days to skip to 15 because I have a lot of builds each month and otherwise the TFS server has trouble to delete the bigger chunks.

$TfsCollectionUrl = "http://YourTfsServer:8080/tfs/YourTeamCollection"
$teamProject = "YourTeamProject"
$BuildDefinition = "YourTeamBuildDefinitionName"

Function CountForward {
    Param([datetime]$startDate,[int]$daysToSkip,[datetime]$endDate)

    Write-Host "Count forward from:" $startDate.ToString("yyyy-MM-dd") -foregroundcolor "magenta"
    Write-Host "Count forward until:" $endDate.ToString("yyyy-MM-dd")-foregroundcolor "magenta"
    Write-Host "Count every" $daysToSkip "day(s)" -foregroundcolor "magenta"

    while ($startDate -le $endDate) {
        $BuildDefinitionFull = $teamProject + "\" + $BuildDefinition
        $dateToQuery = $startDate.ToString("yyyy-MM-dd")

        Write-Host "Delete and destroy Builds before" $startDate.ToString("yyyy-MM-dd") "for build definition" $BuildDefinitionFull -foregroundcolor "magenta"
        
        tfsbuild.exe delete /server:$TfsCollectionUrl /builddefinition:"$BuildDefinitionFull" /daterange:~$dateToQuery /deleteoptions:All /noprompt /silent
        tfsbuild.exe destroy /server:$TfsCollectionUrl /builddefinition:"$BuildDefinitionFull" /daterange:~$dateToQuery /noprompt /silent
        
        $startDate = $startDate.AddDays($daysToSkip)
    }
}
CountForward -startDate (get-Date).AddDays(-300) -daysToSkip 15 -endDate (get-Date).AddDays(-60)

Save the PowerShell file as “DeleteBuildDefinition.ps1” and execute it in your Visual Studio command prompt. You can execute the PowerShell file in your VS command prompt with the following command:

PowerShell -Command "& {D:\DeleteBuildDefinition.ps1}"

tfs delete build definition timeout

Typemock Settings

Embed Typemock in your TFS Build definition

When you want to test your code that uses Typemock, you can use a Team Foundation Server Build Server. The current version of Typemock is 7.4 and this version (introduced in 6.2) has the AutoDeploy feature included. This is very important because now you can use multiple versions of Typemock on one Build server. The reason for that is that you don’t have to install Typemock on you build server anymore. To setup Typemock Autodeploy, you can use the tutorial on their help page in the chapter: Typemock Isolator Integration with Team Foundation Server 2010 (TFS). The only thing that they forgot to mention in the documentation is that there is generated a Typemock directory with a couple of dll’s in it inside your just added AutoDeploy directory. This is done after you fixed the references and restarted Visual Studio. Don’t forget to checkin that directory.

In the help documentation, they say that you have to use the workflow of Typemock to get the AutoDeploy to work. The customer that I now work for already have a custom workflow. I just created that workflow last week with some custom actions for them. So I want to integrate the custom Typemock stuff in the workflow of the customer. The customer works with TFS 2010 (just migrated a few months ago from 2008 so they have a lot of catching up to do) so this blog is aimed at TFS Build 2010. But this will also work for 2012. You can also check the documentation about Typemock with TFS 2012 on their website.

 

The differences between the build templates

There only 4 differences between the template that are special for Typemock. I will show them beneath. The only thing that you have watch for is the right place to put custom activities on the right place.

First open your own workflow in the designer. In your toolbox, add a new category and choose the TypeMock.TFS2010.dll assembly in the installation directory of your Typemock version on your machine. After that, three custom activities are added to your toolbox. Don’t forget to reference the dll in your project where your custom workflow is located.

image

Now add the activities on the right place by dragging them into the workflow. You don’t have to edit any properties. On the left side, you see the default template of TFS 2010. On the right side the template of Typemock. Drag the activities on the same place in your own workflow.

Registreren Typemock

Stoppen Typemock

After that, add a workflow argument of the TypemockSettings type. You can optionally edit the Metadata argument to customize the text that you will see in you build definition.

Typemock arguments

Save your workflow and checkin your workflow. Restart Visual Studio and configure the license in your build definition.

That’s it! It’s very easy. It is not more than 10 minutes of work to edit your own template. When you run your build now with the AutoDeploy feature on and with entering the right license info in your build definition, the build will succeed en will test your Typemock tests.

Creating a TFS Build definition with deploying

This week I was busy to give our environment more quality by adding a deployment of the newly checked in work. This was a quite more difficult then I imagined before I started. This is because the environment that we have is off course not completely the same as the standard demos of Microsoft and the documentation for this is… not available?

 

Team project setup

We have a Team project with 3 different branches.image

  1. Production (Release)
  2. Staging
  3. Development (Debug)

Off course we develop in the Development branch. When the iteration is finished, we merge everything to the staging environment where we and the customer could test everything. When testing (and bug fixing if you made bugs) is done we merge everything to production. In that way we can do bug fixes directly on every version of the project.

 

Build definitions

We wanted to have a build definition for development that:

  1. Builded the solution;
  2. Deploys the multiple projects to the different locations.

I created for each branch a different build definition with different needs to get to the result. I will explain the Development because this build definition will publish multiple ASP .NET Web Applications to different IIS websites.

 

Creating the build definition for development

imageCreate a new build definition and give it the name that you want. I called it Development because I want to use it only on my Development branch in the team project.

I set the trigger to go off on each check-in. In that way, the build will also publish all new versions of the web applications to the desired environments on the server(s).

image

Set the workspace to the workspace of your branch.

Define a drop location and which build controller you like to use of your build server. Maybe you have a dedicated build controller for particular solutions that have many check-ins.

Setup deployment to the server

The last part is the part where we setup the deployment to the server.

image

Define on step 1 the Configurations that you want to build. With config transformations you could setup the different build environments. See for a tutorial this following link:

http://www.asp.net/mvc/tutorials/deployment/deployment-to-a-hosting-provider/Deployment-to-a-Hosting-Provider-Web-Config-File-Transformations-3-of-12

Because it is a development environment, we use the default Debug config with all the links to the test database and test web services. Set the projects to build to the solution file.

 

Note for building only one project
When you set the projects to build to only one project, you could get an error when you are building. The error will say something about your output path that is not right.

c:WindowsMicrosoft.NETFramework64v4.0.30319Microsoft.Common.targets (484): The OutputPath property is not set for project ‘UI.Web.Mvc.csproj’.  Please check to make sure that you have specified a valid combination of Configuration and Platform for this project.  Configuration=’Debug’  Platform=’Any CPU’.  You may be seeing this message because you are trying to build a project without a solution file, and have specified a non-default Configuration or Platform that doesn’t exist for this project.

image

This isn’t really the cause why you would get that error. When you open your project file (unload your project and right click to edit) you will see that the build platform is AnyCPU and not Any CPU. You will have to change the “Configurations to Build” in your build definition to AnyCPU. You can just type it in the dialog.

imageWhen you have a whole solution to build, you don’t need to do this.

 

 

 

 

 

 

Setup deployment for only one web application

When you have only one web application, you can add the “MSBuild Arguments” in your build definition directly.

See for a large explanation for each build argument the following blog:

http://vishaljoshi.blogspot.nl/2010/11/team-build-web-deployment-web-deploy-vs.html

The arguments that you typically have to use are the following:

/p:DeployOnBuild=True
/p:DeployTarget=MsDeployPublish
/p:MSDeployServiceURL=http://servername
/p:DeployIISAppPath=”Default Web Site”
/p:CreatePackageOnPublish=False
/p:MsDeployPublishMethod=RemoteAgent
/p:AllowUntrustedCertificate=True
/p:UserName=username
/p:Password=password

 

Setup deployment for multiple web applications

If you have multiple web applications in a solution (like we have), you can’t use the build arguments like above because then every application would be publishing to the same website on the same server. This will fail your build definition eventually. Maybe not the first time but it will fail sometime. For me it failed every second time I tried it.

Well stop the complaining and tell me how to fix this!

Change the build arguments that you have setup above. Only use the following build arguments:

/p:DeployOnBuild=True
/p:CreatePackageOnPublish=False

image

 

Now unload your projects that you want to publish and edit every project file to their specific needs. Go to the PropertyGroup of your build configuration that you are using in your build definition. I use Debug so will change that PropertyGroup.

image

Use the same name as the build arguments and enter your values.

 

Note for exposing your publish username and password
When you setup your deployment, you have to enter your username and password. Otherwise you will get an error that your not authenticated.

C:Program Files (x86)MSBuildMicrosoftVisualStudiov10.0WebMicrosoft.Web.Publishing.targets (3588): Web deployment task failed.(Remote agent (URL http://servername/MSDEPLOYAGENTSERVICE) could not be contacted.  Make sure the remote agent service is installed and started on the target computer.) Make sure the site name, user name, and password are correct. If the issue is not resolved, please contact your local or server administrator. Error details: Remote agent (URL http://servername/MSDEPLOYAGENTSERVICE) could not be contacted.  Make sure the remote agent service is installed and started on the target computer. An unsupported response was received. The response header ‘MSDeploy.Response’ was ” but ‘v1’ was expected. The remote server returned an error: (401) Unauthorized.

For security reasons, you should not enter your username and password in your build definition. So, how to fix this?

The first thing you must do is give your TFS build service account rights to the server that your publishing to. I added it for now to the local Administrators group of my old (but still working) Windows  Server 2003 server.

The second thing that you have to do depends on which way you have setup your arguments. Use the following syntax for the build arguments in your build definition:
/p:UserName=

And for in your project file:
image

This will indicate that the username and password that will be used for deploying is the same as your build controller on your build server.

Hopefully I gave you enough information about deploying your applications. If you have any questions, don’t hesitate to contact me.

 

Update:
When you deployed your project and see the zip with your project in it, you should check your connectionstring in your config. It could be the case that the connectionstring is using parameters to generate the full connectionstring. This is an option that is on by default. If it is using parameters, you will see something like “$(Replaceable Token…)”.

You can simple disable this (so it will use the connectionstring that you have set in your config transform) by adding the <AutoParameterizationWebConfigConnectionStrings>False</AutoParameterizationWebConfigConnectionStrings> tag in your project file on the same place where you placed the rest of the properties.