Continuous Integration for .Net with Jenkins and NuGet

UrbanThings Head of Platforms, David Else, discusses the challenges of managing internal .Net dependencies and how we’ve created a robust and performant solution to address this.

Many of our platforms here at UrbanThings are built using Microsoft .Net, project dependencies are managed through the use of NuGet packages, and we manage both internal and external packages in the same way. Re-usable, shared components are built into NuGet packages and uploaded to our internal NuGet server, which allows us to easily manage project dependencies, and limit the impact of changes to library code.

One of the major drawbacks to this process occurs when developing locally: when changes need to be made to the shared libraries a developer would need to make their modifications, manually build the libraries, package them, and copy them up to the NuGet server. If further modifications need to be made, this process has to be repeated. This can stifle a developer’s productivity, since they end up spending a lot of time building and packaging libraries instead of writing code.

To solve this problem, we have automated our build processes so that libraries are automatically built, packaged and uploaded to the NuGet server as soon as changes are committed. No more manual updates!

Jenkins is our continuous integration server of choice, mainly because it is very extensible through plugins, and has good coverage of multiple platforms, including .Net, Android and iOS. Using the Multi-Branch Pipeline plugin, Jenkins automatically picks up new branches as they are created within our git repositories, and automatically builds the projects when code is pushed.

The build process goes through a number of steps:

  1. NuGet packages are restored to ensure we have all of the relevant dependencies
  2. The projects are built
  3. Unit tests are run and the results collected
  4. Libraries are packaged
  5. Results are published

The packages are then published to the NuGet server where we have a special feed for development and pre-release packages, plus a production feed which only includes released packages. Any non-NuGet package results are uploaded to Amazon S3, where they are made available for deployment to development, test and production environments. We are also notified via Slack notifications of build completions and failures, so we can quickly and easily react to any issues during the build process.

It now only takes seconds to have code updates included in a library and made available on the NuGet server, and in order to avoid clashing with other developers’ work, the packages are versioned based on the git branch. As well as making our development more productive, this process also encourages developers to use appropriate git-flow feature branches for their work, and encourages them to check in more often.