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:
- The Visual Studio “Publish Windows Azure Application” dialog contains a link to a special page on the Windows Azure Portal that allows you to download a .publishsettings file. This file contains all of the details of your subscription(s), including subscription IDs and certificates.
- The same “Publish Windows Azure Application” dialog allows you to import the .publishsettings file, which results in the certificate being installed on your local machine, and the subscription details imported into a Visual Studio file called Windows Azure Connections.xml (this lives in %UserProfile%\Documents\Visual Studio 2010\Settings). Note that after you import the .publishsettings file you should delete it (or at least protect it) as it contains the full certificate and private key that grants access to your Windows Azure subscription.
- When you are ready to publish your Windows Azure application, you can create a new "publish profile” or use an existing one. A publish profile is saved in your Windows Azure project with a .azurePubxml extension, and contains various details such as your hosted service name, storage account name and deployment slot. The .azurePubxml file doesn’t contain your subscription details, but it does list the subscription name that must correspond to an entry in your Windows Azure Connections.xml file.
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 AzureDeploy.targets file, which is installed on your build server to tell MSBuild to package and deploy your solution to Windows Azure
- The ImportPublishSettings tool, to import a .publishsettings file onto a build server
- The AzureDeploy.ps1 PowerShell script, which also depends on a helper library called AzurePublishHelpers
- A TFS Build Definition that passes properties to MSBuild to initiate the build and deployment process.
The following diagram shows how all the components and files come together, and I’ll describe the details of each below.
The AzureDeploy.targets file
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.
<ProjectToolsVersion="4.0"DefaultTargets="Build"xmlns="http://schemas.microsoft.com/developer/msbuild/2003"><PropertyGroup><PackageName>$(AssemblyName).cspkg</PackageName><PackageForComputeEmulator>true</PackageForComputeEmulator></PropertyGroup><TargetName="AzureDeploy"AfterTargets="Build"DependsOnTargets="Publish"Condition="$(AzurePublishProfile)!=''"><MessageText="Executing target AzureDeploy from AzureDeploy.targets file"/><ExecWorkingDirectory="$(MSBuildProjectDirectory)"Command="$(windir)\system32\WindowsPowerShell\v1.0\powershell.exe -f c:\builds\AzureDeploy.ps1 $(PublishDir) $(PackageName) "Profiles\$(AzurePublishProfile)""/></Target></Project>
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
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):
- publishSetingsFilename: the .publishsettings file to import
- certStoreLocation (optional): the certificate store to which the certificate should be imported. Possible values are CurrentUser (the default) or LocalMachine. You should use CurrentUser if your build process is running as a user account, or LocalMachine if you are running under a system account such as NETWORK SERVICE.
- connectionsFileName (optional): the filename in which the imported settings should be stored. This defaults to “%UserProfile%\Documents\Visual Studio 2010\Settings\Windows Azure Connections.xml”. You may want to change this if your build process is running under a system account such as NETWORK SERVICE.
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
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):
- BuildPath: The folder containing the Windows Azure project on the build server, for example “C:\Builds\1\ProjectName\BuildDefinitionName\Sources\AzureProjectName”.
- PackageName: The unqualified name for the Windows Azure .cspkg name, for example AzureProjectName.cspkg
- PublishProfile: The path to the .azurepubxml file that should be used for deploying the solution. Note that only some of the properties in this file are used for deployment, such as the subscription name, hosted service name, storage account name and deployment slot. Other settings in this file, such as EnableIntelliTrace, are not currently used by the sample scripts.
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 TFS Build Definition
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:
Conclusion
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.