Apr
28
2009
Part #1 of this series I discussed a 5,000 foot elevation of MSBuild and TeamCity and rambled on about Continuous Integration
TeamCity #1: Creating an MSBuild File and talks on Continuous Integration
Round #2
I have mentioned before, I dig anything that can give me greater insight into the code I am writing! Simian, as simple of a concept that it is, does this well! It is also one of those lesser known gems out there!
Simian is yet another one of the tools I like to wear on my belt… Basically, simian will scan you code and find similarities which may come from sloppy coding, or that nasty cut and paste virus that seems to attack many programmers. Sometimes, you don’t even realize that you are doing it, *bad programmer, bad!* but you write code that may, without deeply analyzing your efforts, practically duplicates something you wrote in the application 3 months ago. Hate it when that happens…
Anyway Simian is a great tool, and I highly recommend it. So, in my continued efforts to adopt TeamCity as my CI server of choice it was critical for me to have the ability to incorporate Simian into my build in much of the same fashion that CI Factory does.
Execute command line
The basic command line execution of Simian looks like this;
simian.exe [options] [files]
Here are some of the more important options you can use;
| -language |
Assumes all files are in the specified language Possibilities; java, c#, cs, csharp, c, c++, cpp, cplusplus, js, javascript, cobol, abap, rb, ruby, vb, jsp, html, xml |
| -excludes |
dictates what files to ignore |
| -formatter |
What format the outputted report should be in. Possibilities; are plain, xml, emacs, vs (visual studio), yaml |
| -threshold |
Matches will contain at least the specified number of lines. |
MSBuild Tip #2 : Copying files… http://www.sedodream.com/PermaLink,guid,8f6bbb30-ec22-4fc6-90a1-c32715598d23.aspx MS White Papers and here by Ayende:
What does our MSBuild file look like?
Incorporating this into my MSBuild file we use the Exec task.
How do we get the outputted xml into the TeamCity interface???
TeamCity, when creating Build Report tabs from external program output files only seems to like html, not xml with a xsl file. So, I did what any geek would do, since I didn’t know any better, I rolled my own little down and dirty XML to HTML converter using the XslCompiledTransform class object… It (the converter console app) would only be like three lines of code if I didn’t validate the huevos out of the arguments passed in…
public class Program
{
private const string MissingExtension = "Please enter a valid {0} file, this is missing the extension.";
private const string InvalidExtension = "Please enter a valid {0} file, the file provided has an invalid extension.";
public static void Main(string[] args)
{
if (args.Length < 2)
{
System.Console.WriteLine("Please enter a xsl file and xml file full path.");
return;
}
var xslFile = args[0];
var xmlFile = args[1];
if (!CheckFileNameFormat(xslFile, false))
return;
if (!CheckFileNameFormat(xmlFile, true))
return;
var transform = new XslCompiledTransform();
// Load the XSL stylesheet.
transform.Load(xslFile);
// Transform xml file into an html using the xsl file provided.
transform.Transform(xmlFile, xmlFile.Replace("xml", "html"));
}
private static bool CheckFileNameFormat(string fileName, bool isXmlFile)
{
var extension = isXmlFile ? "xml" : "xsl";
// valida that the argument has a period
if (fileName.IndexOf(".") < 1)
{
System.Console.WriteLine(string.Format(MissingExtension, extension));
return false;
}
var filePieces = fileName.Split('.');
// split on the period and make sure the extension is valid
if (filePieces[filePieces.GetUpperBound(0)] != extension)
{
System.Console.WriteLine(string.Format(InvalidExtension, extension));
return false;
}
return true;
}
}
Then I incorporated it into the Simian target as a new Exec Task like so;
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="RunSimian">
<Message Text="##teamcity[progressStart '***************** Simian...']" />
<Exec IgnoreExitCode="true" Command=""$(ProgramFiles32)\Simian\bin\simian-2.2.24.exe" -formatter=xml:$(MSBuildProjectDirectory)\..\Build\Artifacts\simian.xml -language=cs -excludes=$(MSBuildProjectDirectory)\..\Product\Production\**\*.Designer.cs $(MSBuildProjectDirectory)\Production\**\*.cs" >
</Exec>
<Exec IgnoreExitCode="true" Command=""$(MSBuildProjectDirectory)\..\Build\Packages\XmlToHtmlConverter.exe" $(MSBuildProjectDirectory)\..\Build\Packages\Simian\simian.xsl $(MSBuildProjectDirectory)\..\Build\Artifacts\simian.xml">
</Exec>
<Message Text="##teamcity[progressFinish '***************** Simian...']" />
</Target>
</Project>
One of the important things is to let TeamCity know that the build left a little artifact for it to use in the TeamCity build report. To accomplish this, you need to set the simain.html outputted file up in TeamCity for the build.
Under the General Settings section of the Build configuration in TeamCity there is a section title Artifact paths. JetBrains once again documents out the topic rather well here.
Basically, TeamCity needs to know that there is something for it to pick up and display. Additionally, there are two other things you need to do.
- Set your Build Runner to acknowledge the Simian Build Target
- Amend the main-config.xml file in the Build Server file directory
First, on the Build Runner page of your TeamCity project, there is a handy dandy little textbox for setting up the Targets in your build file that your Build Runner should run;
As you can see here, we have there Targets set to fire in our MSBuild file; BuildSolution, and RunSimian. TeamCity will fire off these Targets when the Build Runner executes.
Secondly, you need to add a line of code to your BuildServer main configuration file typically located here;
C:\BuildServer\config\main-config.xml
What this does is add a new Report tab to your build report. This line should be added with the <server> tags;
<report-tab title="Simian" basePath="" startPage="simian.html" />
I changed up the default simian.xsl file a little to look a little more, ummm… TeamCity like… The output from Simian is placed into our Artifacts directory for our build (see my previous post about folder structure), and TeamCity picks this up and displays it nicely in the report;
Of course, I have no code yet in my projects, so there isn’t any duplication, but I am sure I will rack up a little dupe action once I start coding if I am not paying attention…
So here is the solution up to this point for your reference;
Download
I hope this round shines some light on expanding TeamCity and incorporating external tools into the mix using MSBuild.
Enjoy…
UPDATE 5/20/2009: It was brought up why wouldn't you just use the built in Duplicate Finder Build Runner. For me, I like things to be all inclusive, all analysis under one Build Runner via nAnt or MSBuild. There is a work item (http://jetbrains.net/tracker/issue2/TW-4209) to allow for this functionality on The TeamCity site. But what would this do for personal/ local build outside of TeamCity? It would have to be a component that your MSBuild file could call, and be included with your Third Party dll's in your build harness.