Generating a NuGet package in a localized directory on each build


MSBuild can be a very powerful tool to handle, well, your build process. I will say up front that I haven’t got much experience with it but the little experience I do have, tells me that there are many possibilities to customize your workflow.

The situation that brought me in closer contact with MSBuild is the following: when you create a new project using the Diagnostic with Code Fix template, it will also include a .nuspec file. This file contains the metadata needed to release something on NuGet (name, description, version, release notes, dependencies, etc). It will essentially package your nuspec file into a nupkg file which can in turn be used to publish it onto some feed of your choice. The code in question is the following:

What happens is straightforward: if there is a file called Diagnostic.nuspec and NuGet.exe is packaged with our project, called NuGet.exe and pack the nuspec file into the root directory.

Local feeds

One of the features of NuGet is that it can retrieve packages from different sources and not just the official feed. This is particularly interesting because we can also point to a local folder as our NuGet source! Doing so allows us to manually verify everything works with the NuGet package by using it locally and only publishing it after we are satisfied. However I’m not interested in having to create a separate feed for each project (remember that the OutputDirectory specifies the project root folder).

One more restriction to keep in mind: I don’t want to localize my project’s build structure to work on just my machine. Anyone should be able to pull the repo and get started which means I can’t just hardcode a directory in the MSBuild script.

The problem: how do you create a local NuGet feed that gets the latest version of a NuGet package as soon as I build it, in a location of my choice while keeping other devs in mind?

The solution

The solution I came up with (through some nods on SO) is very straightforward: if a certain environment variable is set, use that variable’s value as the outputdirectory. If it’s not set, use the root. This makes sure that by-default, people will have the same behaviour as a clean project. Only when you want custom behaviour, you should change it. I liked this result a lot because it meant that the project could still be pulled and built cleanly without having to do additional configuration steps (nobody likes doing that for a project you haven’t even started yet).

I added an environment variable with key NUGETLOCAL and value "C:\Users\jeroen\Google Drive\NugetLocal\VSDiagnostics" to my user-level system variables. Note that I added quotes around the value!

Environment variables
Environment variables

All that’s left now is adapting the .csproj file to account for this alternative action:

The code speaks for itself: if the value retrieved from the NUGETLOCAL environment variable is not empty (aka: it has a value), use that as outputdirectory. If it’s empty, use the root.

All that’s left now is setting up the local NuGet feed. You’ll notice that I pointed it to the /Google Drive/NugetLocal folder so I’ll do exactly that under Tools -> Options -> NuGet Package Manager -> Package Sources:

Local feed settings
Local feed settings

Using that feed is now a matter of selecting the correct package source in the NuGet package manager and all local feeds from that folder will show up:

Local feed results
Local feed results
Share on Facebook0Tweet about this on Twitter0Share on LinkedIn0Share on TumblrShare on Google+0Share on Reddit0Flattr the authorDigg this

Leave a Reply

Your email address will not be published. Required fields are marked *