A few months ago I posted on how to automate deployment of Windows Azure projects using MSBuild. While the approach documented in that post continues to work, Windows Azure SDK 1.6 has introduced some new capabilities for managing Windows Azure credentials and publishing settings which I wanted to leverage and build upon. With this new approach, you’ll no longer need to manually manage details such as Subscription IDs, hosted service names and certificates. Because this approach relies on a few tools that are too big to share in a blog post, I’ve also created the Windows Azure Build & Deployment Sample on MSDN which contains all of the tools and sample projects described in this post.
Before we go into details on how the build and deployment process works, let’s look at how Windows Azure SDK 1.6 manages credentials and publishing profiles:
In updating my scripts for automated build and deployment on a build server, I wanted to leverage as much as this as possible, but I needed to build some tools that mirror some of the steps done by Visual Studio’s “Publish Windows Azure Application” dialog, since you may not have Visual Studio installed on your build server.
The build and deployment solution contains the following components:
The following diagram shows how all the components and files come together, and I’ll describe the details of each below.
In my previous post on this topic, I showed you how you can edit your .ccproj project file to define additional targets used in the build process. This approach is still an option, but this time I’ve change my approach by creating a custom MSBuild .targets file which is installed on the build server. This is generally a better option as you don’t need to hand-edit .ccproj files, the custom targets run only on the build server (not on development workstations), and the targets can be reused for multiple Windows Azure projects.
The code included in my AzureDeploy.targets file is shown below. This file needs to be copied to your build server to C:\Program Files\MSBuild\Microsoft\VisualStudio\v10.0\Windows Azure Tools\1.6\ImportAfter, and it will be automatically referenced by the main Windows Azure targets file.
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="AzureDeploy" AfterTargets="Build" DependsOnTargets="Publish" Condition="$(AzurePublishProfile)!=''">
<Message Text="Executing target AzureDeploy from AzureDeploy.targets file"/>
Command="$(windir)\system32\WindowsPowerShell\v1.0\powershell.exe -f c:\builds\AzureDeploy.ps1 $(PublishDir) $(PackageName) "Profiles\$(AzurePublishProfile)"" />
The purpose of this code is to tell MSBuild to package the project for Windows Azure (achieved with the dependency on the Windows Azure SDK’s Publish target) and then call a PowerShell script (you need to change the path depending on how you set up your build server). Note that this target only runs when the AzurePublishProfile MSBuild property is set, which we’ll do later on when we set up the TFS build definition.
Note that you may want to make some other customisations in a .targets or .ccproj file, for example to transform configuration files. I haven’t described this in this post, but there is some information on this in my previous post on this topic.
The ImportPublishSettings tool (available from the Windows Azure Build & Deployment Sample) can be used to import Windows Azure credentials from a .publishsettings file into your build server. It has been designed to operate in the exact same way as the Visual Studio “Publish Windows Azure Application” dialog, so if you have Visual Studio installed on your build server you can use that instead of this tool. Whichever tool you use, this is a one-time process that is completed when you first set up your build process.
This is a simple command line tool which takes 3 parameters (only one of which is required):
If you run the tool under the same account used for your build process, you shouldn’t need to anything more. However if you run it as a different user (for example, you run the script as yourself but your build process runs under NETWORK SERVICE), you will need to open the MMC Certificates snap-in and grant permissions for the certificate private key to the build process’s account.
The AzureDeploy.ps1 PowerShell script is responsible for taking a packaged Windows Azure application and deploying it to the cloud. The sample implementation included in the sample project is pretty simple, and you may want to extend it to perform additional steps such as installing certificates, creating storage accounts, running build verification tests or swapping staging and production slots. There are also a couple of things which you will need to customise depending on if you’re running as a normal user account or a system account. Still, hopefully this script is a useful starting point for your build and deployment process.
The script takes three parameters, which will normally be passed to it by the TFS build process (but you can pass them in yourself for test purposes):
The deployment script depends on a helper library called AzurePublishHelpers.dll (which is also used by the ImportPublishSettings tool), which knows how to read and write from the various files used in the solution. In order to make this library available to PowerShell you will need to install it as a PowerShell module. To this, first open the folder for PowerShell modules, which is “C:\Windows\System32\WindowsPowerShell\v1.0\Modules\AzurePublishHelpers” (replace System32 with SysWOW64 if you’re running your build as 32-bit on a 64-bit system). Then create a folder called AzurePublishHelpers and copy in the AzurePublishHelpers.dll file.
The final piece of the puzzle is setting up one or more Build Definitions. I’m using Team Foundation Server for this, but if you’re using a different ALM toolset you should be able to accomplish something similar.
You can configure your Build Definitions however you want, for example to use different XAML workflows, different settings for running tests, versioning assemblies, etc. You should have at least one Build Definition for each Windows Azure environment you want to deploy to, for example Test, UAT or Production. To configure a Build Definition to deploy to Windows Azure, you’ll need to choose the Process tab and enter the name of your chosen Publish Profile (.azurepubxml file) in the MSBuild Arguments property as shown in the screenshot below:
I hope this post and the accompanying tools and samples help you automate most (if not all) of your Windows Azure build and deployment process. I’ll try to keep the post up-to-date as the platform continues to evolve. If you have questions or comments, please feel free to post here or on the Windows Azure Build & Deployment Sample page.
I am still trying to figure out three things.
How do I pass in the TFS build number to use as the label for my deployment.
How to I pass $Deployment.Url from the powershell script back to TeamBuild so it updates the testsettings for MStest
How do I optionally configure a teardown script for my deployment after the test suite has run. (this one I am sure will involve modifying the workflow)
Hi Philip -
Great questions. I'm far from being an MSBuild expert so I can't fully answer your questions, but I can give some hints.
1. This should be fairly easy. I think the build number is available through the $(BuildNumber) MSBuild variable. You should be able to pass this to the PowerShell script by modifying the AzureDeploy target and of course changing the PowerShell script to use this.
2. I haven't tried this but my understanding is that it's going to be tricky. According to bartdesmet.net/.../invoking-powershell-scripts-from-msbuild.aspx, "if one wants to feed back data from PowerShell to the MSBuild output for instance, a PSHost implementation would be required but that goes far beyond the scope of this post."
3. Tearing down an environment probably means stopping and deleting your Azure deployment, which is easy enough to do using the Azure Management API or via the PowerShell cmdlets. As you say, the trick is figuring out where to plug this code in.
Hope this helps!
We have three subscriptions with hosted services on one Live ID, one for testing, one for release and one for RTM. Is it possible to use the solution described in this post, with for every subscription each an own management certificate?
We have a third party company to manage our Build Server. They are willing to install what is described in this blogpost.
Hi Cesuz -
When you download a .publishsettings file for a Live ID associated with multiple subscriptions, the the same management certificate is used for all of the subscriptions. If you want a different certificate for each, you should either log into a Live ID that is only associated with a single subscription, or you could manage the certificates manually. Either way you'll still be able to use this build process.
The build number was relatively easy. You need to modify the MSBuild command in the teambuild workflow to include the buildnumber, this makes it available in the targets file and can be added to the script command.
The problem with passing back the $Deployment.Url is that there are three layers of execution in this solution and to pass the value on to the MStest task in team build you would need to chain it through Powershell > MSbuild > teambuild. I see no easy way of doing this and hope the product team reinstate the buildnumber by default being passed to MS build and create a mechanism for passing values back up to the teambuild workflow.
I have the tear down script which I could execute after the test task in team build, but as it uses the publishsettings file I am not sure how to find the location of this file as I no longer have the context of the relevant project to get the path.