Integrating StyleCop into Hudson Build

Note: The following doesn’t quite work correctly. Check out tomorrow’s post for more information

After Craig Berntson’s presentation at Boise Code Camp this year on expanding Continuous Integration usage, I decided to take the plunge and implement StyleCop on most of our projects on the CI server.

The problem with StyleCop is that it’s default set of rules are pulled directly from Microsoft’s Design Guidelines for Developing Class Libraries. While many of these guidelines lead to excellent code, they don’t all make sense for every developer. For instance, in our shop, we pefer an indenting style based on the K&R Rules, but StyleCop uses rules more akin to the Allman style. For now, we’ve had to disable several of the styling rules, but I haven’t been able to find (or write) custom rules to fill that need.

That said, it did take me a couple of days of pretty solid work clearing out StyleCop violations before I was comfortable putting it into our rules. Save for disabling all the documentation header rules (we’re likely to apply them, but it will be on a project-by-project basis), I only ended up disabling another fourteen rules in our global stylecop file. Incidentally, one of my favorite default StyleCop features is that it will work it’s way up your directory structure looking for Settings.StyleCop files, which it can parse out for configuration. To facilitate this, I put a StyleCop configuration file at the root of our Perforce depot, which constitutes our global configuration, which still allows us per project configuration if we need to customize anything.

After a few days of work, I had our code down to about 1300 stylecop errors, which was actually a pretty huge code change. The goal, with any code analysis tools, is that they’ll make our programs more maintainable, which is important to me, because I don’t plan to retire from my current employer, and I want to ensure that the codebase I hand off is as healthy as it can be.

Hudson already has a plugin for parsing StyleCop output, among other tools, so it was trivial to configure the addition to our build server. Plus, StyleCop offers an MSBuild task, which is also really convenient. The following code in our core MSBuild file was all it took:

  <UsingTask AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\StyleCop\v4.3\Microsoft.StyleCop.dll"
        TaskName="StyleCopTask" />

    <Target Name="StyleCop">
        <CreateItem Include="..\**\*.cs">
            <Output TaskParameter="Include" ItemName="StyleCopFiles" />
        </CreateItem>
        <StyleCopTask
            ProjectFullPath="$(MSBuildProjectFile)"
            SourceFiles="@(StyleCopFiles)"
            ForceFullAnalysis="true"
            TreatErrorsAsWarnings="true"
            OutputFile=".\stylecop_results.xml" />
    

StyleCop only works on C-Sharp code, but that’s fine for us. VB.Net programmers are currently SOL, but if Microsoft really believe that VB is a first class citizen in the .NET world, I expect we’ll see StyleCop for VB someday. The only other thing to do was make the StyleCop Target a dependency of my full build project, and now StyleCop runs on every build in hudson automatically, and I configured the Violations plugin for each of our projects in Hudson to open ‘**/stylecop_results.xml’, as the StyleCop path and now we’ll have a chart (which will hopefully start trending downward) on our Hudson dashboard telling us how healthy our projects are from a StyleCop perspective. Right now…some are healthier than others.

On a side note, we do have a few open source projects, like the Silverlight Toolkit, which are part of our build process. Since we didn’t write this code, but we still build and link against it, we really didn’t want it to taint our StyleCop score. Excluding a project is as simple as dropping a Settings.StyleCop file in the root of the project that excludes all stylecop rules. Unfortunately, I think you have to name every rule individually, but I am on the lookout for a ‘Exclude this subfolder’ flag for StyleCop.