Continuous integration & deployment of Azure Web Roles using TFS on-premise and WebDeploy - Part 1

Much work has gone into making continuous integration & deployment of Azure Websites as simple and low friction as possible with support for Visual Studio Online, Git and BitBucket etc. For customers and teams still using TFS on-premise and working with Web Roles (Azure Cloud Services) the experience is a little more involved with many resorting to rolling their own solutions, TFS Build Templates and PowerShell scripts, if tools like Octopus Deploy and platforms like appveyor are beyond reach.

Before we proceed a small caveat, in part one we’ll look at automating just the deployment of files and code which have changed. This should suffice for most single instance Dev and Test scenarios, where code is compiled and deployed on hourly, daily cycles. For Production you will also want to deploy the .cspkg file in case Azure reprovisions your Web Role instance(s).

I’ll assume you already have knowledge of the TFS build process, in addition to having source and build TFS server environments configured, I’ll skip straight to the MSBuild parameters as this is where most of the magic happens. I’ll also assume you have the latest Azure SDK and Visual Studio files installed on your build server. By VS files I mean the files required by the BuildProcessTemplate, in my case a customised version of the DefaultTemplate.11.xaml.

PowerShell scripts could be used for the Cloud Service provisioning step however for simplicity I’ve opted for a manual step where I use the Microsoft Azure Publish Settings wizard in VS 2013 and do an initial once off deployment of my Web Role to Azure, making sure to enable Remote Desktop for all roles and Enable Web Deploy for all Web Roles. You will need to take note of the username and password created during this process as they are used later as MSBuild arguments.

Once you have successfully Published your Web Role to an Azure Staging Slot, you will need to repeat the process for the Production Slot, so that we can use the Swap Deployment Slots feature (endpoints have to match) once our tests have passed.

To create a new Dev build definition in Team Explorer I select my preferred Source Setting, Build Defaults, Trigger values, Build Template etc. Note in the MSBuild arguments below UserName and Password are values you defined when using the Microsoft Azure Publish Settings wizard in VS 2013. Moreover I am targeting a Debug build, specifying the VisualStudioVersion which for VS 2013 happens to be 12.0. The MsDeployServiceUrl will always be in the form https://xyz.cloudapp.net:8172/MSDeploy.axd where xyz is either your Cloud Service name or the ID Azure generates for your Staging Web Role.

If you are unsure what this value needs to be go to Server Explorer and drill down the Azure Cloud Services until you find your Staging environment. Selecting the Staging node right click Properties: you will see the value for Name is in the form of a GUID. Use this value and replace xyz. To find your DeployIisAppPath value expand the Staging Node, expand the Web Role and select Instance 0, right click Properties: you will see a Name value in the form Contoso.Web_IN_0. Use this value as your DeployIisAppPath.

So putting it all together, your MSBuild arguments should look something like the following:

1
2
3
4
5
6
7
8
9
10
11
/P:VisualStudioVersion=12.0 
/P:Configuration=Debug
/P:DeployOnBuild=True
/P:DeployTarget=MSDeployPublish
/P:MsDeployServiceUrl="https://8f5c8aa194524f18bd2697675025fdab.cloudapp.net:8172/MSDeploy.axd"
/P:DeployIisAppPath="Contoso.Web_IN_0_Web"
/P:AllowUntrustedCertificate=True
/P:MSDeployPublishMethod=WMsvc
/P:CreatePackageOnPublish=True
/P:UserName="contosomasteruser"
/P:Password="YourPasswordGoesHere"