Setting up NDepend
If you don't know about NDepend, read this first.
...
but its no longer free. Damit.
But I then found SourceMonitor which although far less sexy, is free. And outputs in Xml...which is exactly what we need for integrated CruiseControl.NET reports.
Robin Curry already showed how to integrate them here, but a more appropriate blog entry is here. And read this one too.
Setting up Graph Based Statistics
Then I came across this beautiful post.
Installation was:
Download the latest stable release: CCNetStatisticsGraphs-1.3.zip . Updates are also present at the end of this post if you feel adventurous. [Note: I have a new version available that uses the Dojo library]
Unzip the webdashboard folder over the current CruiseControl webdashboard folder (usually found at C:\Program Files\CruiseControl.NET)
Open the dashboard.config file in the webdashboard folder and change the the projectStatisticsPlugin setting to point to the new StatisticsGraphs.xsl stylesheet, like this:
<projectStatisticsPlugin xslFileName="xsl\StatisticsGraphs.xsl" />
If it everything is in order you should see the following type of report when viewing your project statics...
If that ain't enough, there's another one called <a href="http://www.codeplex.com/ccstatistics">CCStatistics</a>
Visual Interface for editing CruiseControl.NET config file
Try this <a href="http://www.codeplex.com/ccnetconfig">link</a>
Cleaning Up
When ever i clicked the Project Configuration link I got:
The constructor to deserialize an object of type
'ThoughtWorks.CruiseControl.Core.Config.ConfigurationException' was not found.
Cleaning Up: Showing relevant reports only
The tip about updating dashboard.config had shown me the area where
the Reports information was assembled from, and I realized that I could cleanup
the clutter because I don't use all of them.
In other words, just the MSBuild, some NUnit stuff would do nicely for the moment,
and I could always come back later to re-adjust it.
<p/>
Note that a restart of the website (eg: a quick re-save of web.config) is required
for the changes to kick in.
<xslReportBuildPlugin description="MSBuild Output"
actionName="MSBuildOutputBuildPlugin" xslFileName="xsl\msbuild.xsl" />
<xslReportBuildPlugin description="NUnit Details"
actionName="NUnitDetailsBuildReport" xslFileName="xsl\tests.xsl" />
<xslReportBuildPlugin description="NUnit Timings"
actionName="NUnitTimingsBuildReport" xslFileName="xsl\timing.xsl" />
<!-- On Hold
<xslReportBuildPlugin description="FxCop Report"
actionName="FxCopBuildReport" xslFileName="xsl\FxCopReport.xsl" />
<xslReportBuildPlugin
description="NCover Report"
actionName="NCoverBuildReport"
xslFileName="xsl\NCover.xsl" />
<xslReportBuildPlugin
description="Fitnesse Report"
actionName="FitnesseBuildReport"
xslFileName="xsl\FitnesseReport.xsl"/>
-->
<!-- Maybe never need in my case?
<xslReportBuildPlugin description="NAnt Output"
actionName="NAntOutputBuildReport" xslFileName="xsl\NAnt.xsl" />
<xslReportBuildPlugin description="NAnt Timings"
actionName="NAntTimingsBuildReport" xslFileName="xsl\NAntTiming.xsl" />
<xslReportBuildPlugin description="Simian Report"
actionName="SimianBuildReport" xslFileName="xsl\SimianReport.xsl"/>
-->
Note:
The project/workingDirectory is:
"The Working Directory is meant to contain the checked out version of the project under integration."
<tasks>
<logger>C:\Program Files\CruiseControl.NET\server\Rodemeyer.MsBuildToCCnet.dll</logger>
</tasks>
Final Ideas: Unified Reports
<publishers>
<merge>
<files>
<file>D:\CCProjects\xxxx\_msbuild.xml</file>
<file>D:\CCProjects\xxxx\_nunit_*.xml</file>
<file>D:\CCProjects\xxxx\_ncover_*.xml</file>
<file>D:\CCProjects\xxxx\_coverageReport.xml</file>
<file>D:\CCProjects\xxxx\_fxcop_*.xml</file>
<file>D:\CCProjects\xxxx\_sm_*.xml</file>
</files>
</merge>
<xmllogger />
<!--
IMPORTANT:
Point to an *EXISTING* dir to dump the log files used by
CruiseControl.NET Web Dashboard
Dir *must* exist - CC.website bugs out if it doesn't.
It's relative to to the artifact directory.
-->
<xmllogger logDir="BuildLogs" />
</publishers>
http://richardsbraindump.blogspot.com/2007/06/real-world-cruisecontrolnet-setup.html"
The publishers section is where all the xml output files are processed
and merged to produce the information displayed on the web dashboard.
As a naming convention all XML build logs are named as _file.xml.
This makes it easier to clean up things when the next build starts.
Final
Copying a DailyBuild to an output directory.
One could use the BuildPublisher, which is defined as "The Build Publisher lets you copy any arbitrary files on a successful build.".
The words <i>successful build</i> is the key part of course...
The useLabelSubDirectory is "If set to true (the default value), files will be copied to subdirectory under the publishDir which will be named with the label for the current integration. "
Whatever that means (may be the label of the project tag? We'll see.).
<tasks>
...
<buildpublisher>
<sourceDir>C:\myprojects\project1</sourceDir>
<publishDir>\\myfileserver\project1</publishDir>
<useLabelSubDirectory>false</useLabelSubDirectory>
</buildpublisher>
...
</tasks>
Then again, if that is not precise enough you can use
<tasks>
...
<exec>
<executable>make</executable>
<baseDirectory>D:\dev\MyProject</baseDirectory>
<buildArgs>all</buildArgs>
<buildTimeoutSeconds>10</buildTimeoutSeconds>
</exec>
...
</tasks>
Summary/Rules to Follow
State Tag
The state tag's directory attribute must point to:
<div class="UPDATE">
<ul>
<li>It must be an absolute path or you get an error compiling the config file.</li>
<li>The dir must exist.</li>
</div>
<?xml version="1.0" encoding="utf-8" ?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!--
Notes:
$(MSBuildProjectDirectory) is filled in unfortunately, without a final slash...
hence preference for $(BaseDir)
-->
<!-- ************************************************************ -->
<!-- DEFINE COMMON VARIABLES -->
<!-- ************************************************************ -->
<!--
IMPORTANT:
All Dirs must end with slash!!!
-->
<PropertyGroup>
<!-- If unspecified, assume Configuration is 'Debug' -->
<!-- ******************** -->
<!-- ENVIRONMENT / PROJECT VARS -->
<!-- ******************** -->
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<!-- ******************** -->
<!-- MAIN DIRECTORY BRANCHES -->
<!-- ******************** -->
<!-- *** The base dir for whole solution/project is one up, (and has final slash)... -->
<BaseDir>$(MSBuildProjectDirectory)\..\</BaseDir>
<SrcDir>$(BaseDir)SRC\</SrcDir>
<TestsDir>$(BaseDir)TESTS\</TestsDir>
<DocumentationDir>$(BaseDir)DOCUMENTATION\</DocumentationDir>
<BuildDir>$(BaseDir)BUILD\</BuildDir>
<!-- ******************** -->
<!-- ENVIRONMENT / 3rdPARTY -->
<!-- ******************** -->
<!-- NOTE: Make sure all paths end with slashes -->
<NUnitExeDir>c:\Program Files\NUnit 2.4.3\bin\</NUnitExeDir>
<FxCopDir>C:\Program Files\Microsoft FxCop\</FxCopDir>
<SandcastleDir>C:\Program Files\Sandcastle\</SandcastleDir>
<SandcastleBuilderDir>
C:\Program Files\EWSoftware\Sandcastle Help File Builder\
</SandcastleBuilderDir>
<!-- ******************** -->
<!-- THE SRC DIRECTORY / MAIN ASSEMBLY -->
<!-- ******************** -->
<!-- *** SET VAR 1: Enter a single line that describes the assembly -->
<!-- Note: Must have some entry or throws an error. -->
<ProjectSummary>...</ProjectSummary>
<!-- *** SET VAR 1: Enter name of primary assembly, without final dll or exe -->
<MainAssemblyName>XAct.Basics.CleanProject</MainAssemblyName>
<!-- *** SET VAR 2: Specify whether DLL or EXE (just
3 lowercase letters, no DOT before please) -->
<MainAssemblyType>dll</MainAssemblyType>
<!-- *** SET VAR 3: Assembly Language (used by SourceMonitor) -->
<MainAssemblyLanguage>CSharp</MainAssemblyLanguage>
<!-- *** VERIFY VAR: Name of main Assembly (only one). Used by FxCop -->
<MainAssemblyNameFull>
$(MainAssemblyName).$(MainAssemblyType)
</MainAssemblyNameFull>
<!-- The final dir where the assembly will be compiled -->
<MainAssemblyBuildDir>
$(SrcDir)bin\$(Configuration)\
</MainAssemblyBuildDir>
<!-- *** VERIFY VAR: Check that the solution name is
same as primary assembly name, or override -->
<MainAssemblyBuildFile>
$(BaseDir)$(MainAssemblyName).sln
</MainAssemblyBuildFile>
<!-- ******************** -->
<!-- THE TESTS DIRECTORY / UNIT TESTS -->
<!-- ******************** -->
<!-- *** CHECK:
Check that this filter picks up only NUnit tests but leaves
any other pc or other tests -->
<!-- Note that '**\*tests.dll' finds them -
but can't find nunit.framework.dll -->
<NUnitNameFilter>*tests.dll</NUnitNameFilter>
<NUnitTestDir1>$(TestsDir)NUnit.Tests\</NUnitTestDir1>
<NUnitBuildDir1>$(NUnitTestDir1)bin\$(Configuration)\</NUnitBuildDir1>
<!-- *** Common Dir to dump xml reports of various tasks
IMPORTANT:
Most of the Tasks will dynamically shift if you change
this, but SourceMonitor's Export file path
will not...make sure
to change it if you change this variable.
-->
<!-- ******************** -->
<!-- THE BUILD DIRECTORY / BUILD SCRIPT + RESULTING REPORTS -->
<!-- ******************** -->
<BuildReportsDir>$(BuildDir)BuildReports\</BuildReportsDir>
<!-- ******************** -->
<!-- VARS NEEDED BY SOURCEMONITOR -->
<!-- ******************** -->
<SourceMonitorDir>C:\Program Files\SourceMonitor\</SourceMonitorDir>
<SourceMonitorLanguage>$(MainAssemblyLanguage)</SourceMonitorLanguage>
<SourceMonitorTmpDir>$(BuildReportsDir)TMP\</SourceMonitorTmpDir>
<!-- *** Path to where build reports are created ***
Note:
This must contain $(MSBuildProjectDirectory) at some point
because FxCopCmd will be running relative to ITS location,
not this build file
so would not be able to find the output dir.
-->
<!-- *** SourceMonitor tmp xml instructions file contents
Note that I tried to make the export_file
variable abide by $(BuildReportsDir)
by injecting ]]>$(BuildReportsDir)<![CDATA[ in
there...but I didn't get it to work.
At best, I can just dump it
-->
<SourceMonitorTmpCommand>
<![CDATA[
<?xml version='1.0' encoding='UTF-8' ?>
<sourcemonitor_commands>
<write_log>false</write_log>
<command>
<project_language>CSharp</project_language>
<project_file>
..\BUILD\BuildReports\TMP\TempProject.smp
</project_file>
<source_directory>..\SRC\</source_directory>
<include_subdirectories>true</include_subdirectories>
<export>
<export_type>2</export_type>
<export_file>
..\BUILD\BuildReports\sourcemonitor-fullresults.xml
</export_file>
</export>
</command>
</sourcemonitor_commands>
]]>
</SourceMonitorTmpCommand>
<!-- ******************** -->
<!-- VARS FOR SANDECASTLE BUILDER -->
<!-- ******************** -->
<SandcastleBuilderExe>
SandcastleBuilderConsole.exe
</SandcastleBuilderExe>
<!-- SandcastleArgs must be all on one line as it doesn't work
if there are linefeeds in it to make it more readable... -->
<!-- Note: 'addContent' flag accepts quotes
around first arg, but not second. -->
<!-- Note: doesn't like windows slashes very much...
double them up to non-escape -->
<!-- Note: if output is abstract, will be put
relative to SandlecastleExe -->
<!-- Suprisingly, DocSrc\*.*",DocSrc\\,False, has
to have one slash
then two...or it truncates... aggravating -->
<!-- so this was folded just for blogging.... make it all on one line -->
<SandCastleArgs1>
-new -HelpFileFormat=website -PresentationStyle=prototype -NamingMethod=MemberName
-SyntaxFilters="Standard" -SdkLinkType="Msdn" -ContentPlacement="AboveNamespaces"
-IncludeFavorites="False" -BinaryTOC="True" -PurgeDuplicateTopics="True"
-ProjectLinkType="Local"
-MissingTags="Summary, Parameter, Returns, AutoDocumentCtors"
-VisibleItems="InheritedMembers, Protected, SealedProtected"
-RootNamespaceContainer=true</SandCastleArgs1>
<!-- so this was folded just for blogging.... make it all on one line -->
<SandCastleArgs2>
-Preliminary="true" -assembly="$(MainAssemblyBuildDir)$(MainAssemblyNameFull)"
-dependency="$(MainAssemblyBuildDir)*.*"
-addContent="$(DocumentationDir)DocSrc\*.*",DocSrc\\,False
-OutputPath="$(DocumentationDir)Output\\"</SandCastleArgs2>
<!-- so this was folded just for blogging.... make it all on one line -->
<SandCastleArgs3>
-ProjectSummary="$(ProjectSummary)"
-CopyrightText="Copyright XAct Software Solutions Inc. 2007"
-CopyrightHref="http://legal.xact-solutions.com/copyright/" </SandCastleArgs3>
<SandCastleUnused>
-HTMLHelpName="Assembly Documentation"
-FeedbackEMailAddress="support07@xact-solutions.com"
-HeaderText=""
-FooterText=""
-helpTitle="An XAct Software Solutions, Inc."
-ContentSiteMap="$(DocumentationDir)DocSrc\\content.sitemap"
</SandCastleUnused>
<SandeCastleExtra>
-CleanIntermediates=True
<SandcastlePath path="" />
<WorkingPath path="" />
<CppCommentsFixup>False</CppCommentsFixup>
<FrameworkVersion>2.0.50727</FrameworkVersion>
<RootNamespaceTitle />
<Language>en-US</Language>
<FeedbackEMailAddress />
</SandeCastleExtra>
</PropertyGroup>
<!-- ************************************************************ -->
<!-- IMPORT MSBUILD EXTENSIONS -->
<!-- ************************************************************ -->
<!--
VERY VERY IMPORTANT:
Import the MSBuild Community Extension pre-defined Tasks
or Nunit testing won't work:
-->
<!-- folded for blogging only -->
<Import Project="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\
MSBuild.Community.Tasks.Targets" />
<!-- ************************************************************ -->
<!-- TARGET: PROPERTIES -->
<!-- ************************************************************ -->
<Target Name="Properties">
<Message Text=" " />
<Message Text=" " />
<Message Text=" " />
<Message Text="==================================================" />
<Message Text="PROPERTIES " />
<Message Text="==================================================" />
<Message Text="Target: '$(Target)'" />
<Message Text="Condition: '$(Configuration)'" />
<Message Text="MSBuildProjectDirectory: '$(MSBuildProjectDirectory)'" />
<Message Text=" " />
<Message Text="BaseDir: '$(BaseDir)'" />
<Message Text=" " />
<Message Text="MainAssemblyName=$(MainAssemblyName)" />
<Message Text="MainAssemblyType=$(MainAssemblyType)" />
<Message Text="MainAssemblyLanguage=$(MainAssemblyLanguage)" />
<Message Text="MainAssemblyNameFull=$(MainAssemblyNameFull)" />
<Message Text="SrcDir=$(SrcDir)" />
<Message Text="MainAssemblyBuildDir=$(MainAssemblyBuildDir)" />
<Message Text="MainAssemblyBuildFile=$(MainAssemblyBuildFile)" />
<Message Text=" " />
<Message Text="NUnitExeDir=$(NUnitExeDir)" />
<Message Text="TestsDir=$(TestsDir)" />
<Message Text="NUnitNameFilter=$(NUnitNameFilter)" />
<Message Text="NUnitTestDir1=$(NUnitTestDir1)" />
<Message Text="NUnitBuildDir1=$(NUnitBuildDir1)" />
<Message Text=" " />
<Message Text="FxCopDir=$(FxCopDir)" />
<Message Text=" " />
<Message Text="BuildDir=$(BuildDir)" />
<Message Text="BuildReportsDir=$(BuildReportsDir)" />
</Target>
<!-- ************************************************************ -->
<!-- TARGET: BUILD -->
<!-- ************************************************************ -->
<Target Name="Build">
<Message Text=" " />
<Message Text=" " />
<Message Text=" " />
<Message Text="==================================================" />
<Message Text="*** MSBUILD" />
<Message Text="==================================================" />
<Message Text="Vars Used:" />
<Message Text="MainAssemblyBuildFile=$(MainAssemblyBuildFile)" />
<Message Text=" " />
<!-- ******************** -->
<!-- Build specified *.proj or *.sln file -->
<!-- ******************** -->
<Message Text="*** MSBuild Starting..." />
<MSBuild Projects="$(MainAssemblyBuildFile)" Targets="Build" />
<Message Text="*** MSBuild Complete." />
</Target>
<!-- ************************************************************ -->
<!-- TARGET: UNITTESTS -->
<!-- ************************************************************ -->
<Target Name="Tests" DependsOnTargets="Build">
<Message Text=" " />
<Message Text=" " />
<Message Text=" " />
<Message Text="==================================================" />
<Message Text="*** NUNIT TESTS" />
<Message Text="==================================================" />
<Message Text="Vars Used:" />
<Message Text="NUnitExeDir=$(NUnitExeDir)" />
<Message Text="TestsDir=$(TestsDir)" />
<Message Text="NUnitNameFilter=$(NUnitNameFilter)" />
<Message Text="NUnitTestDir1=$(NUnitTestDir1)" />
<Message Text="NUnitBuildDir1=$(NUnitBuildDir1)" />
<Message Text="BuildReportsDir=$(BuildReportsDir)" />
<Message Text=" " />
<!-- ******************** -->
<!-- Make sure the xml output dir exists -->
<!-- ******************** -->
<Message Text="Making Report Directory..." />
<MakeDir Directories="$(BuildReportsDir)" />
<Message Text="Done." />
<!-- ******************** -->
<!-- Import all the NUnit Test dlls from the test dir, filtered by Name -->
<!-- ******************** -->
<!--
<ItemGroup>
<Stuff Include="$(TestsDir)$(NUnitNameFilter)/>
</ItemGroup>
-->
<CreateItem Include="$(NUnitBuildDir1)$(NUnitNameFilter)">
<Output ItemName="UnitTests" TaskParameter="Include" />
</CreateItem>
<!-- FOR A SECOND TEST UNIT -->
<!--
<CreateItem Include="$(NUnitBuildDir2)\*tests.dll">
<Output ItemName="UnitTests2" TaskParameter="Include" />
</CreateItem>
-->
<!-- ******************** -->
<!-- Run tests on files within this item...-->
<!-- ******************** -->
<!-- Note that you can also combine several
assemblies with 'Assemblies="@(UnitTests);@(UnitTests2)"'-->
<Message Text="NUnit Testing Starting..." />
<NUnit
ToolPath="$(NUnitExeDir)"
Assemblies="@(UnitTests)"
ContinueOnError="false"
OutputXmlFile="$(BuildReportsDir)nunit-results.xml"
/>
<Message Text="NUnit Finished." />
</Target>
<!-- ************************************************************ -->
<!-- TARGET: FXCOP ANALYSIS -->
<!-- ************************************************************ -->
<!--
Notes:
FxCopCmd looks for the assembly relative to itself...
To get around it:
a) skip using WorkingDirectory, and instead combine both like this
"C:\Program Files\Microsoft FxCop\FxCopCmd.exe"
so as to not switch directory...
or
b) ensure the path to the assembly file at some point
contain the $(MSBuildProjectDirectory) macro,
which it does here by including $(MainAssemblyBuildDir)
-->
<Target Name="FxCop" DependsOnTargets="Build;">
<Message Text=" " />
<Message Text=" " />
<Message Text=" " />
<Message Text="==================================================" />
<Message Text="*** FXCOP" />
<Message Text="==================================================" />
<Message Text="Vars Used:" />
<Message Text="FxCopDir=$(FxCopDir)" />
<Message Text="BuildReportsDir=$(BuildReportsDir)" />
<Message Text="MainAssemblyBuildDir=$(MainAssemblyBuildDir)" />
<Message Text="MainAssemblyNameFull=$(MainAssemblyNameFull)" />
<Message Text=" " />
<Message Text="NUnit Testing Starting..." />
<MakeDir Directories="$(BuildReportsDir)" />
<Message Text="Done." />
<Message Text="FxCop Beginning..." />
<!-- so this was folded just for blogging.... make it all on one line -->
<Exec WorkingDirectory="$(FxCopDir)"
Command="FxCopCmd.exe
/f:$(MainAssemblyBuildDir)\$(MainAssemblyNameFull)
/out:$(BuildReportsDir)fxcop-results.xml" />
<Message Text="FxCop Finished." />
</Target>
<!-- ************************************************************ -->
<!-- SOURCEMONITOR METRICS -->
<!-- ************************************************************ -->
<Target Name="Metrics" DependsOnTargets="Build">
<Message Text=" " />
<Message Text=" " />
<Message Text=" " />
<Message Text="==================================================" />
<Message Text="*** SOURCEMONITOR METRICS" />
<Message Text="==================================================" />
<Message Text="Vars Used:" />
<Message Text="BuildReportsDir=$(BuildReportsDir)" />
<Message Text="SourceMonitorDir=$(SourceMonitorDir)" />
<Message Text="SourceMonitorLanguage=$(SourceMonitorLanguage)" />
<Message Text="SourceMonitorTmpDir=$(SourceMonitorTmpDir)" />
<Message Text="SourceMonitorTmpCommand=$(SourceMonitorTmpCommand)" />
<Message Text=" " />
<MakeDir Directories="$(SourceMonitorTmpDir)" />
<!-- ******************** -->
<!-- *** Create and Dump the pre-made lines from
the defined property into the tmp xml file -->
<!-- ******************** -->
<WriteLinesToFile
File="$(SourceMonitorTmpDir)SourceMonitorCommands.xml"
Lines="$(SourceMonitorTmpCommand)"
Overwrite="true"
/>
<!-- ******************** -->
<!-- *** Run SourceMonitor Metrics while
staying relative to this build dir -->
<!-- ******************** -->
<!-- so this was folded just for blogging.... make it all on one line -->
<Exec
Command=""C:\Program Files\SourceMonitor\SourceMonitor.exe"
/C $(SourceMonitorTmpDir)SourceMonitorCommands.xml" />
<!-- *** Convert the SourceMonitor Output into a more usable summarized version -->
<Xslt
Inputs="$(BuildReportsDir)sourcemonitor-fullresults.xml"
Xsl="$(SourceMonitorDir)SourceMonitorSummaryGeneration.xsl"
Output="$(BuildReportsDir)sourcemonitor-results.xml"
/>
<!-- ******************** -->
<!-- *** Remove the intermediate files -->
<!-- ******************** -->
<!-- so this was folded just for blogging.... make it all on one line -->
<!-- all on one line please:
<Delete Files=".\BuildReports\sourcemonitor-
fullresults.xml;$(SourceMonitorTmpDir)TempProject.smp;
$(SourceMonitorTmpDir)SourceMonitorCommands.xml" />
<RemoveDir Directories="$(SourceMonitorTmpDir)" />
-->
</Target>
<!-- ************************************************************ -->
<!-- DOCUMENTATION -->
<!-- ************************************************************ -->
<Target Name="Documentation" DependsOnTargets="Build">
<Message Text="SandcastleBuilderExe Beginning..." />
<!-- folded for blogging only -->
<Exec WorkingDirectory="$(SandcastleBuilderDir)"
Command="$(SandcastleBuilderExe)
$(SandcastleArgs1) $(SandcastleArgs2) $(SandcastleArgs3)" />
<Message Text="c Finished." />
</Target>
<!-- ************************************************************ -->
<!-- FINAL COPY OUT -->
<!-- ************************************************************ -->
<Target Name="AfterDropBuild">
<!-- Delete old source code docs -->
<CreateItem Include="\\tfsserver\Code Documentation\MyProject\**\*.*">
<Output TaskParameter="Include" ItemName="DocDeployFiles" />
</CreateItem>
<Delete Files="@(DocDeployFiles)" />
<!-- Copy new source code docs to team system -->
<CreateItem Include="$(SolutionRoot)\DOCs\**\*.*"
Exclude="$(SolutionRoot)\src\Help\Working\**\*.*">
<Output TaskParameter="Include" ItemName="NewDocFiles" />
</CreateItem>
<!-- folded for blogging only -->
<Copy SourceFiles="@(NewDocFiles)"
DestinationFolder="\\tfsserver\Code Documentation\
MyProject\%(NewDocFiles.RecursiveDir)" />
</Target>
<!-- ************************************************************ -->
<!-- CRUISECONTROL.NET -->
<!-- ************************************************************ -->
<Target Name="CCNET" DependsOnTargets="Tests;FxCop;Metrics">
</Target>
</Project>
Stupid Monkey
Now...after all this work, it suddenly dawned on me that I was going to have to update my add this MSBuild file to all my old projects.
And that was going to take some time...which I didn't have.
So I then realized I may want to actually keep the build file on the build server, and have the cruisecontrol config file call it with parameters.
A little research led me to the p flag of MSBuild which allows the passing in arguments that are then referencable from inside the build file.
/p:FxCopDir="C:\Program Files\Microsoft Visual Studio 8\Team ... "
Further Reading
Came across <a href="http://robotdeveloper.wordpress.com/2007/06/08/nunit-failed-test-fails-cruisecontrolnet-build/">this</a> in terms of how to work with NUnit and its marking the whole thing as failed when just one test fails...
Excellent on how to use MSBuild rather than NAnt:
http://www.testearly.com/2007/06/20/running-mstest-against-net-20-on-cruisecontrolnet/
Acknowledgements
The most famous link to learning how to set up CruiseControl.NET has to be
http://joefield.mysite4now.com/blogs/blog/archive/2005/12/04/7157.aspx" CruiseControl.NET from Scratch v1.0
but I found the following links were just as important, if not clearer:
In fact, this http://thesprage.com/DasBlog/PermaLink,guid,9cf95a80-2ba9-4d84-924b-5d8d440cedd7.aspx Sprag's page was great.
http://weblogs.asp.net/jdanforth/pages/How-to-Hook-Up-a-VS.NET-2005-Solution-With-CruiseControl.NET-in-a-Few-Minutes.aspx
Where to put your NUnits
http://codebetter.com/blogs/jeremy.miller/archive/2006/10/07/Week-1-Questions_3A00_--How-do-you-organize-your-NUnit-test-code_3F00_.aspx
Observations:
tasks/msbuild/workingDirectory
System.IO.DirectoryNotFoundException: Directory does not exist: E:\BuildArtifacts\XAct.Drawing.DoubleBuffer\TESTS\ at