« Tip: use ‘Twitter Search’ to get great info on events happening now | Main | How to fix the error: “The communication object, System.ServiceModel.Channels.ServiceChannel, cannot be used for communication because it is in the Faulted state” when running a Windows Azure project in the local development fabric/emulator »

How to automate the creation of a Windows Azure 1.3 package in Team Foundation Server (TFS) for a web role hosted in ‘Full IIS’ with multiple sites

For the last few months we have automated the deployment of our Windows Azure web and worker roles – with a couple of clicks we can compile, package, deploy and run our latest bits in the Azure cloud!

image  A sequence of activities in our TFS Build XAML workflow –
notice the first step is to create the Azure Package

We use Team Foundation Server 2010 (TFS) and one of the steps is to create the .CSPKG file – the windows azure package that needs to be uploaded to blob storage before you can use the Azure Management APIs to deploy and run your service. 

Below I have some details on how to get that working with the latest Windows Azure SDK, version 1.3.  Note that you could use a different source control system and something like Cruise Control .NET (http://cruisecontrol.sourceforge.net/) to automate the deployment of your web and worker roles – the principles are the same.

Update 2/25: Tom Hollander has a great post on his blog on how to achieve the same thing – check out the section “Supporting Multiple Sites per Role”, where he makes sure the azure project depends on the ASP.Net projects (the sites) and transforms the ServiceDefinition.csdef file to make sure the assemblies for the second site are included in the package -

Using MSBuild to deploy to multiple Windows Azure environments
http://blogs.msdn.com/b/tomholl/archive/2011/02/23/using-msbuild-to-deploy-to-multiple-windows-azure-environments.aspx

Good times!

As a side note, I hope Microsoft will provide some direction on how to properly automate the creation of an azure package in TFS 2010, without having to manually scan the target builds installed with the azure SDK.


How to create a Windows Azure package in Team Foundation Server (TFS)
(when you have multiple sites hosted in ‘Full IIS’ in one Azure web role)

To create the Azure package, with the Azure SDK 1.2 and below, I was using an invoke process workflow activity and calling CSPACK.  Unfortunately, this stopped working after I installed the Azure SDK 1.3 and I started using the “Full IIS” feature to host multiple sites in one web role.

Here’s how you can create your Azure Package in TFS if you have a web role hosted in ‘Full IIS’ with multiple sites -

Step 1 – Edit your Azure project (.csproj) and change the build target

Open your windows azure project (the one that contains your web and/or worker roles) in Visual Studio and edit the project file (.csproj) in the XML editor.

Change the project’s ‘DefaultTargets’ from ‘Build’ to -

DefaultTargets="PrepareForPackaging;Build;CheckRoleInstanceCount;CopyServiceDefinitionAndConfiguration;
ConfigureWebDeploy;IntelliTrace;CorePublish”

So your project XML will look something like this -

image

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="PrepareForPackaging;Build;CheckRoleInstanceCount;CopyServiceDefinitionAndConfiguration;
ConfigureWebDeploy;IntelliTrace;CorePublish" xmlns="
http://schemas.microsoft.com/developer/msbuild/2003">
  …
</Project>

Step 2 – Create a pre-build event that compiles all of the sites included in your web role

The only way I found to make sure all of the sites deployed in my web role 
included all of the needed assemblies was to have a pre-build event on my
azure project that compiled each site.

You can easily do that by right-clicking on your project > Properties > 
Build Events > and editing the ‘Pre-build event command line’ -
image
You can also edit your project XML directly like we did in step 1-
image
  <PropertyGroup>
    <PreBuildEvent>
        echo PREBUILDSTEP for $(ProjectName)

        %windir%\Microsoft.NET\Framework\v4.0.30319\msbuild $(ProjectDir)\..\..\
Source\[MYPROJECT].Web.[MYSITE1]\MYSITE1.csproj
        if errorlevel 1 goto BuildEventFailed

        %windir%\Microsoft.NET\Framework\v4.0.30319\msbuild $(ProjectDir)\..\..\
Source\[MYPROJECT].Web.[MYSITE2]\MYSITE2.csproj
        if errorlevel 1 goto BuildEventFailed

        REM Exit properly because the build will not fail
        REM unless the final step exits with an error code
        goto BuildEventOK
        :BuildEventFailed
        echo PREBUILDSTEP for $(ProjectName) FAILED
        exit 1
        :BuildEventOK
        echo PREBUILDSTEP for $(ProjectName) COMPLETED OK
    </PreBuildEvent>
  </PropertyGroup>
</Project>
If I didn’t do this, I would find that after deploying, some assemblies were missing 
from the azure package (even though I did set ‘copy local=true’ for the assemblies
in the project and my solution compiled in TFS did include the sites themselves) -

image

Note: once you make these changes, your compilation time in Visual Studio may increase, since you will be building the Azure package every time you compile. 

We tend to run and debug our web sites in IIS in local development and we end up unloading the azure projects during development – so this is not an issue for us.

Step 3 – Edit your TFS Build XAML workflow and add a “MSBuild” activity

1) In your XAML workflow, after your project/solution has been compiled, add an activity of type “Microsoft.TeamFoundation.Build.Workflow.Activities.MSBuild” -

image

Make sure you choose your targets to be “CorePublish” (although since we edited the project directly, this matters less) -

image

That’s it!  Now with one click you can compile, run your tests, and create the windows azure package to deploy your web role hosting multiple sites to the cloud!

Inside Baseball - How I got this working

After our automatic deployments to the Azure cloud stopped working, I had some talks with my co-worker M. and some discussions with @smarx and others in this thread -

One web role with two sites:
how do I package it in TFS or using msbuild tasks?


http://social.msdn.microsoft.com/Forums/en-US/windowsazuredevelopment/thread/fd15652e-c7b5-41de-a235-6602b470d9d1

which got me digging into the MSBUILD tasks that are installed by the Azure SDK here:

C:\Program Files (x86)\MSBuild\Microsoft\Cloud Service\1.0\Visual Studio 10.0\Microsoft.CloudService.targets

Final note: Development, QA, and Production environments

Just a quick note on our software development process – we have three different branches in source control, corresponding to our three environments. 

Our TFS build XAML workflow can handle all three environments/branches and deploys our services (the web and worker roles) differently depending on the arguments – here’s an example of our schedule:

image

Make sure your XAML workflow can handle different environments and different services – it will save you tons of time.

Good times!


| More



Comments

Powered by
Movable Type 3.35