Continuous integration and delivery to Azure websites with Bamboo

Fortunately for Azure developers, there are many great ways to set up continuous delivery (CD) to Websites. I use Bamboo CI server.

Continuous integration and delivery to Azure websites with Bamboo

Fortunately for Azure developers, there are many great ways to set up continuous delivery (CD) to Websites. For less complex continuous integration (CI) scenarios, I use kudu deployment scripts in conjunction with the built-in support for Github, Bitbucket, and TFS. In a more complex scenario that requires additional steps like unit test runners for both .NET and JavaScript, I use Bamboo CI server. As build servers go, Bamboo has quickly become one of my favorites. And if your ALM lives in the Atlassian world as mine does, integration between tools like JIRA, Stash, and Confluence makes Bamboo the ideal CI server in your DevOps workflow.

Set up your build plan

This is pretty straightforward if you set up a build in other build servers like TeamCity or TFS Build services. In the case of a .NET app, you'll check out your code, run Nuget package restore, run MSBuild against your sln or csproj, and finally, publish your results as an Artifact (more on that later).

Once your plan is set up, you can define the tasks for your build. A basic 3-step plan of code checkout, package restore, and build is the ideal starting point. Once that's working well, you can add other, more customized tasks like test runners.

For the Script task, I'm calling the nuget.exe I've added it to my repository to supply custom credentials for my private feeds in my nuget.config. Another great way to do this in Bamboo is to add the nuget.exe as a custom executable in the server configuration. Once added, you can use the Command task to call Nuget and pass in any arguments.

For the build step, I'm using the MSBuild task, specifying the version, and then passing in the configuration argument for a Debug build.

Now that the Tasks are set, I want to do one last thing: publish my build output as a shared artifact to make it available to my deployment project. Via the Artifacts tab, I select Create definition, and then name and supply the pattern for the files to become available.

Set up your deployment

First, create a new deployment project and link it to the build plan you just created. Your new project will allow you to set up one or more environments to promote/deploy your builds. For example, you may want to enable CD to your development website but you also want the ability to promote a build directly to production.

For each environment you set up, you'll be able to set up the tasks necessary for deployment and its triggers and notifications. For example, you'll want to trigger a deployment to your development website after each successful build on your main develop branch but would not want that same trigger on your staged production environment.

To make the actual deployment to my Azure website, I'm using an MSBuild task against my build output artifact, supplying the /p:DeployOnBuild command along with the /p:PublishProfile with a few additional arguments to make the deployment happen successfully. The critical requirement here, however, is that I've already downloaded my publishing profile from the Azure portal for my Website and have imported it into my project via the Publish dialog in visual studio.aspx). The only customization I've made to the imported profile was to remove the password so that it's not stored in source control, allowing me to pass it as an argument to my MSBuild deployment task.

So why MSBuild and not WebDeploy? Web deploy is incredibly difficult to use from the command line, as many will attest to. I've tried and failed myself, so I've ultimately settled on this reliable and customizable deployment method. And while I'm essentially building the project twice, there is very little overhead in doing so. It even gives you an opportunity to tune your deployment build with additional arguments, like switching to Release (with config transforms) when promoting a dev build to production.

commit -> trigger build -> successful -> trigger deployment -> deployment complete -> ask for raise