Continuous Integration Using NuGet And TeamCity

If you are building software which will be distributed using NuGet packages, it is a good idea to continuously build those packages as part of the Continuous Integration (CI) process. This for instance allows you to continuously integrate the resulting packages in test clients, or have internal teams working with an early development build of the product. No matter where you host or publish your packages, they are built in the same way. A NuGet package itself is unaware of its whereabouts.

This article helps you improving your continuous integration process with TeamCity, turning it into a continuous flow of NuGet packages.

Introducing NuGet

NuGet, originally called NuPack, is a solution-level package manager developed both inside and outside of Microsoft as part of an Outercurve Foundation (formerly Codeplex Foundation) project. It’s been around for over a year now and is continuing to thrive on its success. It is even being standardized as the way Microsoft will distribute its components, including the ASP.NET webstack which is now being developed in the open.

So why NuGet? At the moment, the NuGet Gallery on nuget.org has over 5000 unique packages available for you to incorporate into your solution at the click of a button or a single Powershell command from within Visual Studio.

The introduction of NuGet has led to a huge improvement in the way we are using open source components. All the great .NET community libraries and applications are now only a search box away and they all adhere to a consistent method for distribution and installation whatever the package hosting site you’re searching. Because of that, the upgrade experience and reuse of software components has improved as well. Whether you are consuming binaries or source code files, with NuGet in general, you are referencing a released product, which is a NuGet package with a specific version. Even pre-release packages have a specific version. That’s why proper versioning is key when building a NuGet package, as it is the first technical constraint and contract between the package, the package manager, and its consumers. If you mess up the version number, you risk breaking the install or upgrade experience of the consumer, not to mention the consuming project itself! Doing this regularly will push people away from using your package in the long term.

Package Versioning

It’s clear that you need to think about your versioning strategy when publishing NuGet packages. Although you are not required to, it’s a good idea to keep the package version in sync with the assembly version of the component you are shipping inside. If you have multiple components to ship, each with their own version, it effectively means they have their own lifecycle and releases, so you should create multiple NuGet packages and make them dependent upon one another.

You can read up on the NuGet documentation site on how you can explicitly specify the version of a package and its dependencies inside the NuGet package manifest (or .nuspec file).

If you’re not sure about when or how to change a version number, I’d recommend reading up on the Semantic Versioning Specification (SemVer), which is probably really close to something you already do today. A semantic version can be presented as following, with optional parts between square brackets:

MAJOR.MINOR.PATCH[-PRERELEASE][+BUILD]

The specification is still in pre-release stage and NuGet already supports the bigger part of it, but not yet to its full extent. This is due to the fact that the team is waiting for SemVer to become RTM to finalize on its implementation.

Note: NuGet currently does not support a build number for pre-release packages and the SemVer specification requires you to only increment either the major, the minor or the patch number by one between two non-pre-releases.

While in the end, SemVer is a single versioning specification, NuGet currently supports two types of semantic versions. Choose either one of them, depending on whether the package is an internal CI build or is to be published into production. Any package source that is readily available for consumption is considered to be production because any package published on such feed can be consumed immediately.

Packages published into production can be split into actual releases and pre-releases. Pre-releases have the same versioning specification as releases, with the addition of a dash and a pre-release-tag appended to the patch version number.

Packages that are created as a result of Continuous Integration build should use an auto-incremented build number and cannot contain a pre-release-tag. Note that NuGet separates the patch number and the build number using a dot (.) instead of the plus (+) sign which is used by SemVer.

Production major.minor.patch[-prerelease]
Continuous Integration major.minor.patch[.build]

To summarize, SemVer mainly comes down to the following versioning strategy:

Major version increment Indicates breaking changes in public API
Minor version increment Indicates backwards compatible changes in the public API (e.g. additions)
Patch version increment Internal bugfixes, not affecting the public API
Pre-release tags Indicates a pre-release, sorted alphabetically (Alpha > Beta > RC etc.)
Build number Identifies a unique build of a package, internal use only

Continuous (Package) Integration

Upgrading your CI process to continuously create NuGet packages means adding a few extra steps to your CI build:

  • When using a no-commit strategy for your NuGet dependencies, you need to restore them in a pre-compilation step
  • You need to create the NuGet packages in a post-compilation step
  • You need to publish the resulting NuGet packages on a package repository, preferably one that is dedicated to CI packages.

Introducing TeamCity

There is one CI tool which really stands out at the moment, making it very smooth and easy for you without having to deal with too much MSBuild configuration or too many project modifications: JetBrains’ TeamCity. At this moment, TeamCity is the only CI tool that comes with a built-in NuGet server and built-in support for installing, producing and publishing NuGet packages. You can even trigger a build when a new or update package becomes available on a specified package source. You can read more on this functionality on the TeamCity blog.

To get you started, the following sample scenario will compile a solution, build a nuget package for a project, and publish it. Both the NuGet command line and the NuGet Visual Studio extension provide you with options to configure and use custom package sources. Behind the scenes, TeamCity makes good use of the NuGet command line. More specifically, the nuget.exe install, pack and push commands are being used. The install and push commands both have a –Source option, while the pack command comes with a –OutputDirectory option. TeamCity uses this to provide you with a convenient user interface where you can choose to use the NuGet.org official feed, the TeamCity built-in NuGet feed or your own custom package source, for instance a network share or a feed on MyGet.org.

If you don’t have access to a TeamCity server and want to give this scenario a try, you can download and use a free Professional license of TeamCity from http://www.jetbrains.com/teamcity/download. The free version is fully functional and has no time limit. However, it is constrained to a maximum of 20 build configurations so if you need more you can consider buying or getting a 60-day evaluation of the TeamCity Enterprise Server license. Installation is very straightforward and takes only a few minutes. Installation instructions and configuration help can be found on the TeamCity Confluence documentation site.

Configuring TeamCity’s NuGet features

First, install a version of the NuGet commandline utility, which is required for the NuGet build steps that will install, package and publish the packages. To do so, navigate to the TeamCity administration page and click on the NuGet Settings section. Notice that you can have multiple versions of nuget.exe next to each other.

N.B. Due to a glitch in TeamCity 7.0, NuGet 2.0 is not available as an option yet. This has been fixed in v.1 which is already available via Jetbrains’ Early Access Program.

The version of NuGet already installed in TeamCity

Choosing a version of NuGet to download and install

Once you’ve done this, you can go ahead and set up your CI project for your solution. Create a new project and a new build configuration that connects to your version control server of choice and make sure you have a build step that simply compiles your solution. You don’t need to change anything in your solution or project files with regards to NuGet. If you enabled package restore, that’s fine, if you didn’t and wish to check in your packages, that’s fine as well.

You should now have the following build steps configured.

Your build steps i TeamCity before adding NuGet Packaging

Creating NuGet packages post-build

The next task is to add the NuGet packaging step. You have a few options for different approaches:

  • Target the project file itself
  • Target the project file and have a nuspec file next to it
  • Target a nuspec file directly.

Either way, TeamCity supports all three of them as illustrated in the new build step below.

After the compilation step, add a new build step of type NuGet Pack and select a NuGet commandline version to be used.

Add a NuGet Pack step to your build

Next, specify the projects or NuGet manifests you want to package in the Specification files textarea. Note that MSBuild-style wildcard characters are supported for easy configuration. The following are examples of how to configure the Specification files.

  • **\*.csproj (recursive enumeration of all *.csproj files in the working directory)
  • *.nuspec (enumeration of all *.nuspec files in the root of the working directory)

Obviously, you can combine these for a more advanced selection of projects and manifests to be packaged. In addition, you can set the package version and provide a base directory to be used for packaging.

Setting your package parameters in the build step

As soon as you create NuGet packages as build artifacts and the NuGet feed is enabled, those packages will be picked up.

Checkbox to enable creating NuGet packages as build artifacts

When the resulting packages end up in your build artifacts, you can manually inspect them or even download them from within the TeamCity web interface.

The TeamCity web interface showing your NuGet packages as build artifacts

To enable the TeamCity NuGet server, navigate to the TeamCity administration page and click on the NuGet Settings section. Enable the feed, and enable the guest account if you want to have a feed that doesn’t require authentication. The URL’s below are the ones you’d need to configure in your Visual Studio development environment.

TeamCity's NuGet RSS feeds for use in Visual Studio

Publishing NuGet packages

If you decided to use the TeamCity built-in NuGet feed, you’re done already. This step is not required for you.

However, if you do not want to publish to the built-in NuGet feed, the last step is to publish these newly created packages onto your own repository for consumption. This is an optional but recommended step to consume the newly created packages with test clients. You could also immediately deploy them as a production release if you have a bulletproof continuous delivery approach or just like living on the edge.

Adding a NuGet Publish Step to your build

The NuGet Publish build step supports nuget.org out-of-the-box, so there’s no need to specify the target package source URL if that’s where you want to publish your packages. You only need to specify a target feed when you want to publish onto your own feed. The API key however is required.

Configuring Package Source and API Key for the uGet publish step

Conclusion

In this article, you’ve learned how you can approach NuGet package versioning in various ways and how it affects your release process and your package management infrastructure, as well as the consumer experience. Whatever versioning scheme you use, make sure you have a strategy and take into account the way NuGet deals with build version numbers and pre-release tags.

Using a continuous integration tool can help you a long way in automating package creation, consumption, integration testing and publication. TeamCity supports this out-of-the-box using configurable build steps which can be set up with a few clicks.

You might also like...

Comments

Contribute

Why not write for us? Or you could submit an event or a user group in your area. Alternatively just tell us what you think!

Our tools

We've got automatic conversion tools to convert C# to VB.NET, VB.NET to C#. Also you can compress javascript and compress css and generate sql connection strings.

“Every language has an optimization operator. In C++ that operator is ‘//’”