Wednesday, November 19, 2014

Continuous Deployment Notes

Preface

Continuous integration and deployment are important concepts in efficiently delivering products. Here's some notes I've made about setting up a continuous deployment pipeline using TFS, TeamCity, and Octopus Deploy. It's a work in progress, but I hope it will help someone else out there.

The Process

The process is pretty simple. Code is checked into source control. A build server picks up the changes. It uses a build script to create a .nupkg file containing the build artifacts. This .nupkg file is uploaded to an Octopus-hosted NuGet repository. Octopus is then used to deploy the artifacts to a target environment.

The Build Server

Here's some details on the build server. It is a Server 2008 R2 machine with SP1. It's got .NET 4.5.1, Visual Studio and TeamCity installed. Some things were dropped into a 'Tools' directory on the main drive: MsBuildTasks, a custom Regex task, NuGet, NUnit, and Octo.exe.

The Sample Project

I'll be using a small, sample project illustrate where things go, and how they are used. The project structure, as it is checked into source control is similar to the following:

./SampleProject/
 SampleProject.proj
 src/
  SampleProject.sln
  Version.cs
  SampleProject.Host/
  SampleProject.Library/
  SampleProject.Library.UnitTests/

The Project File

The sample project uses the SampleProject.proj file to define the steps necessary for building the solution. Using a project file allows us to have a (mostly) product independent build sequence. All the major steps for creating a product artifact are codified in the project file. Be sure to check out the project file documentation on MSDN's site.



Yes, it could use some cleanup, but this is what's running now. It was originally designed to work with either Jenkins or TeamCity. It's being updated to work only with TeamCity.

Why use a file instead of setting the steps up in TeamCity? With the exception of the NUnitTeamCity addin, the script can be used in Jenkins. That means you can pick this file up and go with whatever CI server you want. I'm hoping to post something about that later. It's also easier for me to visualize the build process in one file, versus the million option pages that is TeamCity.


Versioning

Mike Hadlow has a pretty nifty trick for assembly versions in a solution. It uses one file to set the version information for all the artifacts in a solution. His blog post explains it. I'm a big fan of Semantic Versions. Using the one-file trick really eases process of maintaining the changes to the version numbers.

Using the one-file trick, it became possible to use a regex task to update the file. This made it possible to have the version number based on the TeamCity build number. A co-worker found the build task, so I'm not sure where it originally came from. This custom task is also added to the Build Server's tools directory.




TeamCity

The bummer about TeamCity is the clicky-ness of the interface. There are roughly a million different links, each leading to a new page. Each page has a dozen or so things you can set. Sure, it's amazingly powerful and flexible. But, it's easy to get lost. This isn't a knock on TeamCity. I'm just easily confused.

The first thing to set in TeamCity is the build number format. This is accessible on the first page of the build configuration settings.

Note: The format of the variable changes when used in a MSBuild file. In the project file, the any '.' in the variable name must be replaced with an '_'. That means 'build.number' becomes 'build_number'.



Octopus

Using Octopus to deploy is a straightforward process: create an environment, add some machines, create a release. Installing Octopus and tentacles on target machines is covered in the Octopus online documentation.

The first step is to create an environment. Once the environment is setup with machines, a project is needed. Finally, a release is created to actually deploy the artifacts. Once the environment is setup, you can perform your deployment as normal.



Octopus is pretty flexible in terms of the scripting and other custom install actions. The sample project is a TopShelf service. Installing and uninstalling it just needs a couple custom actions around the deploy action.

-

The scripts can be as simple as, C:\Services\SampleProject\SampleProject.Host.exe uninstall.


Wrapping It Up

Hopefully this will help someone resolve some of the issues with setting up a CI build process.