Adding Code Metrics to your Team Foundation Server 2013 Build

2014-09-09

When implementing a Deployment Pipeline for your application, the first step is the Commit phase. This step should do as many sanity checks on your code as possible in the shortest amount of time.Later steps will actually deploy your application and start running all kinds of other tests.

One check I wanted to add to a Commit phase was calculating the Code Metrics for the code base. Code Metrics do a static analysis on the quality of your code and help you pinpoint those types or methods that have potential problems. You can find more info on Code Metrics at MSDN.

Extending your Team Foundation Server Build

Fortunately for us, TFS uses a workflow based process template to orchestrate builds. This workflow is based on Windows Workflow Foundation and you can extend it by adding your own (custom) activities to it.

If you have a look at GitHub you’ll find a lot of custom created activities that you can use in your own templates. One of those is the Code Metric activity that uses the Code Metric Powertool to calculate Code Metrics from the command line.

If you check the documentation, using the Code Metric activity comes down to downloading the assemblies, storing them in version control and then adding the custom activity to your build template.

And that would be true if you wouldn’t be running on Visual Studio/Team Foundation Server 2013. For example, check the following line of code on GitHub:


string metricsExePath = Path.Combine(ProgramFilesX86(),
       @"Microsoft Visual Studio 11.0Team Tools
         Static Analysis ToolsFxCopmetrics.exe");

This code still points to the old version of the Code Metrics Powertool. There where also some other errors in the Activity. For example, setting FailBuildOnError to false won’t have any effect.

Fortunately, all the activities are open source. Changing the path was easy. Fixing the FailBuildOnError bug was a little harder since it’s impossible (to my knowledge) to debug the custom activities directly on the Build server.

But there is a NuGet package for that

But as a good developer, we first create a unit test that shows the bug really exist. By fixing the unit test, we then fix our bug. Unit testing Workflow activities is made a lot easier with the Microsoft.Activities.UnitTesting NuGet package.

Using this NuGet package I came up with the following ‘integration’ test:


[TestMethod]
[DeploymentItem("Activities.CodeMetrics.DummyProject.dll")]
public void MakeSureABuildDoesNoFailWhenFailBuildOnErrorIsFalse()
{
    var activity = new CodeMetrics();

    var buildDetailMock = new Mock<IBuildDetail>();
    buildDetailMock.SetupAllProperties();

    var buildLoggingExtensionMock = new Mock<IBuildLoggingExtension>();

    var host = WorkflowInvokerTest.Create(activity);
    host.Extensions.Add<IBuildDetail>(() => buildDetailMock.Object);
    host.Extensions.Add<IBuildLoggingExtension>(() =>
           buildLoggingExtensionMock.Object);
    host.InArguments.BinariesDirectory = TestContext.DeploymentDirectory;
    host.InArguments.FilesToProcess = new List<string>
    {
       "Activities.CodeMetrics.DummyProject.dll"
    };

    host.InArguments.LinesOfCodeErrorThreshold = 25;
    host.InArguments.LinesOfCodeWarningThreshold = 20;

    host.InArguments.MaintainabilityIndexErrorThreshold = 60;
    host.InArguments.MaintainabilityIndexWarningThreshold = 80;

    host.InArguments.FailBuildOnError = false;

    try
    {
        // Act
        host.TestActivity();

        Assert.AreEqual(BuildStatus.PartiallySucceeded,  
                 buildDetailMock.Object.Status);
    }
    finally
    {
        host.Tracking.Trace();
    }
}

I’ve configured the Code Metrics activity to run the analysis against a Dummy project dll with some threshold settings and of course the FailBuildOnError set to false. Fixing the test is left as an exercise to the reader ;)

Extending the Build Template

As a final step I’ve added parameters to configure the different thresholds and some other important settings to the Build workflow. That way, a user can configure the Code Metrics activity by editing the Build Definition:

Configure Code Metrics in Build Definition

And that’s it! You can download the code with the modified activity code, the workflow unit test and a copy of an implemented build workflow template here.

Useful? Feedback? Please leave a comment!