Aug 232012

Lately I’ve been playing with the new NuGet integration that is baked into TeamCity 7.X. It works great, and has almost all of the features that I was looking for. However, there still needs to be some thought put toward how you should configure your project for publishing packages. For example, do you want new packages generated and published every time a developer commits a change, or only on demand when a candidate build is vetted as “stable”? TeamCity gives you all of the Lego blocks you need to get the setup you want, but you still have to arrange those blocks in the way that makes sense for you and your team. In this post I’m going to describe the setup that I recommend for publishing NuGet packages with TeamCity.

This is the workflow we’re looking to achieve:

  • Developer commits changes to the project
  • TeamCity detects change, fires off continuous build
  • As part of continuous build, “unstable” NuGet package is created and published
  • Team vets the changes, and eventually decides to publish “stable” package
  • Developer clicks a button in TeamCity to fire off stable build
  • As part of stable build, stable NuGet package is created and published

A note about versioning

The versions in these examples follow the recommendations in my post on syncing versions between TeamCity, NuGet, and .NET assemblies. This is not required to achieve the above workflow, but it definitely helps keep things sane.

Creating the unstable build

This piece is fairly simple, and is the bread and butter of TeamCity. We point TC at our source code repository, and anytime a change is detected, a build is fired off. My unstable build is configured with standard build steps, such as actually executing the build against the Visual Studio solution. I’m not going to go into detail on that stuff. The build step that is important for our purposes is the final one, which uses the NuGet Pack build runner.

Most of the settings for the NuGet Pack build runner are fairly straightforward, but the key for achieving unstable builds is the version number:

Note the “-unstable” at the end of the version number. This takes advantage of the Prerelease feature of NuGet. Packages that follow the convention of appending their version number with “-something” are considered prerelease, and are only visible to people that choose to show prerelease packages.

The other setting to worry about is to make sure that TeamCity publishes the created package as an artifact of the build.

Enabling NuGet server within TeamCity

If you don’t want to publish your packages on the NuGet Gallery (for example if you are creating packages for internal use), it used to be a bit of a pain to manage an internal NuGet server, or use a shared folder which doesn’t have all of the features. Luckily, with TeamCity 7.X, a NuGet server is built in, and works perfectly.

To enable the server, just navigate in TeamCity to Administration > NuGet Settings. On the NuGet Server tab, make sure that the server is enabled. Also, you probably want to make sure that guest authentication is enabled, because you want to use the public URL in Visual Studio to connect.

At this point, you can add the Public Feed URL to the Package Sources within Visual Studio, and any packages published by TeamCity will be visible in your Visual Studio projects.

By the way, if you do want to publish your packages from TeamCity to the public NuGet Gallery, TeamCity provides a NuGet Publish build runner. I have not used it, so I can’t comment on how well it works. But it is there if you need it.

Using unstable packages

Now that the TeamCity NuGet server is enabled, it should be automatically pulling in any packages that are published as build artifacts. Our unstable packages should be included in the feed. However, by default, the NuGet UI within Visual Studio does not show prerelease packages. To use them, change the dropdown that says Stable Only to Include Prerelease. Once you do that, you should see the unstable packages that are being published by TeamCity.

Creating the stable build

Now we want to create a second build configuration in the same project within TeamCity. This build will not have any triggers, because we only want to fire it off on demand. Also, we don’t want to actually do another Visual Studio build, so really the only build step is likely to be another NuGet Pack.

But here’s the tricky part: we need this build to use the same files as the unstable build. In order to achieve this, we can use TeamCity dependencies to copy settings from one build to another. First, set up an artifact dependency from the stable build to the unstable build.

The weird part is we don’t actually use this artifact dependency for anything directly, but it does let us take advantage of a TeamCity Dependency Properties to use properties from the main build in this new one. And that means that we can set our NuGet Pack folders based on the checkout directory of the unstable build.

It also lets us set the version number of the stable build to be the same as the unstable one, without duplicating the logic that creates the build number (DRY for the win!).

Note that in your setup, you probably need to change the “bt2″ to whatever the build ID is for your unstable build created above.

And we’re done!

That’s pretty much it. At this point you should have TeamCity automatically creating unstable / prerelease packages and publishing those to its internal NuGet server. In addition, a developer can run the stable build on demand to take the bits from the most recent unstable build and publish them as a stable package. Depending on how brave a developer is, they can either set their Visual Studio to consume the unstable builds, or wait for the stable builds. The level of integration between TeamCity, NuGet, and Visual Studio makes for a very simple and powerful setup for managing dependencies between .NET projects.

 Leave a Reply



You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>