Failure is inevitable

I’m a big fan of psake for build and deployment automation. I know there are a ton of tools for this sort of thing out there, but as an avid user of Powershell, writing build and deploy scripts with psake feels more natural than the alternatives. In this post, I’ll show you how you can use psake to automate publishing NuGet packages.

Why psake?

I chose psake primarily because I love Powershell, and because I found psake scripts to be far cleaner than similar scripts that I’ve created using MSBuild and NAnt. With psake, it is very easy to script out even complicated steps, and since you have the full capabilities of Powershell at your disposal, you’re unlikely to find any step in your deployment process that can’t be automated.

Folder Setup

Below is the folder structure I’ve adopted for deployments (check it out on github). I’ve got a couple of Powershell scripts and my NuGet spec file. The batch script and the corresponding “publish.ps1” Powershell script exist simply to support “double-click to publish,” so I don’t even have to pop open a Powershell console to kick off a new release anymore.

The “default.ps1” script is a psake build script that contains the actual meat of the deployment process. Let’s dive in to that and see how it all works.

Using psake to Build Your Solution

A typical psake build script consists of properties (which can be overridden later when you invoke the build) and tasks. My build script for packaging and publishing SpecsFor is no different. Check it out:

One interesting thing to note is how the $Version property is populated. I’ve taken an approach similar to the one described by Joshua Flanagan: I’ve tagged the major version number of SpecsFor using the “git tag" command, and I’m determining a minor version number based on how many commits there have been since the last major version number. It’s not perfect, but it works.

Aside from that interesting tidbit, the rest of the script is fairly simple. The “Init” task just clears the console, the “Clean” task removes output files that might be left over from a previous run, and the “Build” task just builds the solution and redirects the output using the excellent PublishedApplications package. The interesting tasks are Archive, Pack, and Publish. Let’s look at each in turn.

Creating an Archive

Releases of SpecsFor are published in two different ways. The first is as a NuGet package, the second is as a zip file. The “Archive” task automates the creation of the zip file.

The task copies the required assemblies as well as Resharper and Visual Studio templates to a temporary folder, then uses PSCX’s Write-Zip cmdlet to create a zip file. After that, it’s a simple, but manual, process of uploading the zip to github (if anyone knows of a way to automate that piece, let me know!).

Creating a NuGet Package

The “Pack” and “Publish” tasks are responsible for creating a NuGet package and publishing it to www.nuget.org respectively. Let’s start with “Pack:”

First, the task attempts to remove a package with the same version number you are about to publish. This makes the task repeatable, as attempting to push a version that already exists will make “nuget.exe” throw an error. Finally, the package can be published using the “nuget push” command. Assuming you have your API key saved, this step will publish the package without requiring you to manually specify your API key each time.

Final Thoughts

Creating a NuGet package can be a little tricky, but with a little Powershell magic, you can automate the process. I’m using this process to publish SpecsFor, and I plan to apply it to other packages I publish on NuGet in the future as well. I might even package up this deployment process itself as it’s own NuGet package! Let me know if you’d like to see that.

About Matt Honeycutt...

Matt Honeycutt is a software architect specializing in ASP.NET web applications, particularly ASP.NET MVC. He has over a decade of experience in building (and testing!) web applications.
He’s an avid practitioner of Test-Driven Development, creating both the SpecsFor and SpecsFor.Mvc frameworks.

He's also an author for Pluralsight,
where he publishes courses on everything from web applications to testing!