Background
The TFS Community Build Extensions provide many activities to enhance your build. One we use a lot is the one for StyleCop to enforce code consistency in projects as part of our check in & build process.
In most projects you will not want a single set of StyleCop rules to be applied across the whole solution. Most teams will require a higher level of ‘rule adherence’ for production code as opposed to unit test code. By this I don’t mean the test code is ‘lower quality’, just that rules will differ e.g. we don’t require XML documentation blocks on unit test methods as the unit test method names should be documentation enough.
This means each of our projects in a solution may have their own StyleCop settings file. With Visual Studio these are found and used by the StyleCop runner without an issue.
However, on our TFS build boxes what we found that when we told it to build a solution, the StyleCop settings file in the same folder as the solution file was used for the whole solution. This means we saw a lot of false violations, such as unit test with no documentation headers.
The workaround we have used to not tell the TFS build to build a solution, but to build each project individually (in the correct order). By doing this the StyleCop settings file in the project folder is picked up. This is an OK solution, but does mean you need to remember to add new projects and remove old ones as the solution matures. Easy to forget.
Why is it like this?
Because of this on our engineering backlog we have had a task to update the StyleCop task so it did not use the settings file from root solution/project folder (or any single named settings file you specified).
I eventually got around to this, mostly due to new solutions being starting that I knew would contain many projects and potentially had a more complex structure than I wanted to manage by hand within the build process.
The issue is the in the activity a StyleCop console application object is created and run. This takes a single settings file and a list of .CS files as parameters. So if you want multiple settings files you need to create multiple StyleCop console application objects.
Not a problem I thought, nothing adding a couple of activity arguments and a foreach loop can’t fix. I even got as far as testing the logic in a unit test harness, far easier than debugging in a TFS build itself.
It was then I realised the real problem, it was the StyleCop build activity documentation, and I only have myself to blame here as I wrote it!
The documentation suggests a way to use the activity
- Find the .sln or .csproj folder
- From this folder load a settings.stylecop file
- Find all the .CS files under this location
- Run StyleCop
It does not have to be this way, you don’t need to edit the StyleCop activity, just put in a different workflow
A better workflow?
The key is finding the setting files, not the solution or project files. So if we assume we are building a single solution we can use the following workflow
Using the base path of the .sln file do a recursive search for all *.stylecop files
Loop on this set of .stylecop files
For each one do a recursive search for .cs files under its location
Run StyleCop for this settings file against the source files below it.
This solution seems to work, you might get some files scanned twice if you have nested settings files, but that is not a issue for us as we place a StyleCop settings file with each projects. We alter the rules in each of these files as needed, from full sets to empty rulesets of we want StyleCop to skip the project.
So now I have it working internally it is now time go and update the TFS Community Build Extensions Documentation