StyleCop, NuGet Package Restore and Jenkins: beware, caustic mixture

Individually, they’re lovely: now it’s open-source, StyleCop seems to be (finally!) getting the love and attention it needs, NuGet has rapidly come of age to be the one-stop-shop for package management in .NET without the angle-bracket heartache that is Maven, and Jenkins, well, Jenkins just rocks.

But together they don’t play nice at all.

The latest releases of StyleCop are available as nice NuGet packages. Superficially this is appealing, as we can simply

PM> Install-Package StyleCop

to add static file checking goodness to our projects. Nothing more needs to be done, hurrah.

Also, the latest version of NuGet supports “Package Restore”. Usually NuGet puts the binaries that it’s downloaded into a /packages folder in your solution hierarchy. This is fine when you’re working locally, but you don’t really want to put binaries into a source control system: they cause all kinds of issues with bloated repositories, make for slow download times, and are generally frowned upon. So Package Restore tweaks a project to download any missing NuGet packages automatically when the project is built.

But. If you combine the two…

Internally, StyleCop alters a project file to load the StyleCop MSBuild target. But, if you are using Package Restore, you won’t have the target available until the project is built.

The latest version of the StyleCop package works around this by adding a check to see if Package Restore is enabled and the package hasn’t yet been downloaded. If that’s the case, it lets you build the project but spits out an error:

Failed to import StyleCop.MSBuild targets from
'..\packages\StyleCop.MSBuild.4.7.34.0\tools\StyleCop.targets'.
The StyleCop.MSBuild package was either missing
or incomplete when the project was loaded
(but is now present). 

To fix this, restart the build.
If you are using an IDE (e.g. Visual Studio),
reload the project before restarting the build. 

Note that when using regular NuGet package restore
(during build) the package will not be available for
the initial build because the package needs
to be present before the project is loaded. If package
restore executes successfully in the intitial build
then the package will be available for subsequent builds. 

If this is an automated build (e.g. CI server), you
may want to ensure that the build process restores
the StyleCop.MSBuild package before the initial build.

Phew!

So, spelling misteaks aside, do what it says: close down Visual Studio, re-open the solution, and all should be well, as the previous build did the Package Restore.

But that won’t work for a build server: your Jenkins job will fail.

The answer is to… do what it says, and restore the StyleCop package before the job runs. Here’s a bit of MSBuild that does that:

<ItemGroup>
 <NuGetPackageConfigs Include="$(MSBuildStartupDirectory)\**\packages.config" />
</ItemGroup>

<Target Name="LoadNuGetPackages">
   <Message Importance="high" Text="Retrieving packages for %(NuGetPackageConfigs.Identity)" />
   <Exec Command='$(MSBuildStartupDirectory)\.nuget\nuget install %(NuGetPackageConfigs.Identity) -o $(MSBuildStartupDirectory)\packages' />
</Target>

If you make this a pre-condition of your solution build, this will pre-load all the NuGet packages before the build runs — so the projects will resolve their StyleCop targets properly first time.

Author: Jeremy McGee

I write software, and try to help others do the same.