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
- Production (Release)
- 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.
We wanted to have a build definition for development that:
- Builded the solution;
- 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
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).
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.
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:
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:\Windows\Microsoft.NET\Framework64\v4.0.30319\Microsoft.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.
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.
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:
The arguments that you typically have to use are the following:
/p:DeployIISAppPath=”Default Web Site”
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:
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.
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)\MSBuild\Microsoft\VisualStudio\v10.0\Web\Microsoft.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:
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.
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.