Deploying Cloud Services with TeamCity and Octopus Deploy
This is an older post published on my blog on Jan 23 2015, I’m moving a few old posts over here.
What are we doing?
We’re going to use our continuous integration pipeline to build, test and deploy an Azure Cloud Service. The process we work with requires that work isn’t just pushed into production before going through a review process; as such it’s quiet important that the steps to get the application deployed when reviewed is as simple as posible. This is part of a larger system they will move our code production from a single press of the “Approve” button.
I’m going to make some assumptions here:
- You’re using Azure Cloud Services and you have a service setup. This can be done via powershell or the portal. You don’t need to have deployed into it, but it needs to be waiting for you.
- You are using TeamCity.
- You are using Octopus Deploy.
- You’re using NUnit for your tests. This is the step I’ll show here but you can insert your own test runner steps. (You are unit testing this, right?)
Hopefully even if you are using a different toolchain you’ll be able to see what’s going on here and adapt it to your own tools.
Setting the project up
We need to start in visual studio. Sadly we can’t just use octopack like we would with other projects as you can’t currently add nuget projects to a “.ccproj” file. We’ll start by creating a folder called “deployment” within our cloud service project. Within this folder we’ll place a nuspec file that is going to be used to tell teamcity what files to add to the nuget package.
Octopus Deploy essentially just extracts files from the nuget package and places them in the correct place so this is where we make sure our cloud service files get included. Add the following to “package.nuspec”:
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"> <metadata>
<description>Cloud Service Package</description>
<file src="..\bin\Release\app.publish\*.*" target="" />
Make sure to include this in the files you commit to your repository.
Hopefully this doesn’t seem like I’m skipping over things but I’m not sure this is the place to explain TeamCity in great detail. You need to:
- Setup a project.
- Add a build configuration for this deployment.
- Attach your repository settings and any triggers you want.
Now we can look at the build steps. I’m going to be building this project twice, which initially seems a bit weird, but there is a method to my madness. I want to make sure that all of the projects in my solution build and that all of the tests pass before I even think about building a package to deploy.
My first step is a “Nuget Installer”. I won’t bother showing you the setup here, all you have to do is give it the path of your solution file and TeamCity will even fill that in for you if you click the little button to the right of the box.
Second step is a “Build Solution” step. In this step you again pass the location of your solution but also a couple of other bits; you may need to expand the advanced options for some of these.
- I set my “targets” to “rebuild”.
- I set my “configuration” to “release”. This is your transforms.
- Finally I set “command line parameters” to “/p:TargetProfile=Cloud /p:Configuration=Release”. Similar to configuration but it also passes the cloud service target.
- I stare longingly at the octopack option that would make this so much simpler.
The third step is my unit test runner. I use NUnit and pass in “\bin\Release*UnitTests.dll”** which will find all of my projects that end in “UnitTests” and execute them. You can add your test runners here.
I leave all of my steps setup with “If all previous steps finished successfully” as the “Execute step” option but this is particularly important if you want to stop the build on failing tests.
At this point we are happy to go ahead and package the cloud service. Personally I take this opportunity to publish a couple of shared libraries to our internal nuget feed as we have access to all of the build artifacts.
Add an “MSBuild” step to your project and point the “Build file path” to your .ccproj file; you can use TeamCity to help with their magic button to the right with this again. We have a few different settings this time:
- I set my “targets” to “publish” as we want to publish the service.
- I set the “command line parameters” to “/t:Publish /p:TargetProfile=Cloud /p:Configuration=Release /p:PublishDir=bin\Release\app.publish\”
- Again, I stare longingly at the octopack option that would make this so much simpler.
When TeamCity gets this far we’ll be have our package ready to bundle up in the nuget package. Tasty octopus food. Go ahead and add a “Nuget Pack” step to your project, then:
- Specify your nuspec file. This is the one we created earlier in the deployment folder.
- Give it a version number. We do something clever with automatic versioning but you can put your version variable in here until I get around to writing that process up!
- Set your output folder. This is going to depend on how your going to publish the nuget file. I set mine to “Build/packages” because I’ve set “Artifact paths” to “Build/packages/** =>” in General Settings. If you have nuget enabled for TeamCity then this will put your packages in that feed.
- Finally in “Properties” I set “Configuration=Release”.
If your not using the built in TeamCity nuget feed you’ll now need to setup a “Nuget Publish” step to place your package in that feed. If not your all set with TeamCity for now, hit the run button and make sure everything stays green. We’ll be back in a moment to configure the deployment trigger when we’ve setup octopus.
In octopus you need to create yourself a project and go to the process tab on the left, keep a not of the name for later. Click to add a step and then choose “Deploy to Windows Azure”. When this step opens we’ll need to set some stuff up.
- Select your machine roles. For Azure deploys I just install a tentacle on the same machine as the server and give it a role named “Azure”.
- Select your package. You need to have configured the feed inside octopus. If you have it’ll give you some help by listing the different packages.
- “Subscription id” is pretty self explanatory, you get this from your Azure subscription portal.
- “Cloud service” is the name of your cloud service you created in the portal earlier.
- “Storage account” this is where octopus is going to upload your nuget package before deploying it into the cloud service.
- Follow the instructions for adding the certificate if this is your first time.
- Finally you get to configure the slot you want to deploy into. Here I’ve just got “production” at the moment.
- Instance count is interesting, you can choose wether to ignore the scaling configuration in your project if Azure has already scaled your service further. This make most sense for deploying over the top of a service, you wouldn’t want to be under heavy load and have the service kill lots of instances.
- Select your environment and save.
Now you can add any other steps you’d like. We have emails and some hipchat notifcations that go out before and after the actually deployment.
Back to TeamCity
In the build configuration from before you need one final step, add a “Deploy Release” step. The first thing you’ll need to set in here is the location of your octopus server and the api key that you can get from your user profile on there. Then you can add:
- The project name you noted down when creating it in octopus to “Project”.
- Your release number to “Release number”, this is probably similar to your build number before.
- Your environment name depending where your deploying. Mine is “production”.
- You can pass extra command line parameters. I send my package number as I don’t always just want the latest: “ — packageversion %Major.Minor.Build%.%build.number%”.
We’re done. Run your build configuration and if all has gone to plan you’ll see it deployed into Azure!