Cruise Control.NET File Merge NUnit File - Getting XmlException - msbuild

I am new to Cruise Control. I'm running a project where I use an MSBuild file to build my project. I'm using the NUNit task in the MSBuild Community Tasks project to run all of my unit tests and output an xml file with the test results with this command:
<NUnit Assemblies="#(OutputFiles)" WorkingDirectory="$(UnitTestResultsLocation)"
OutputXmlFile="$(UnitTestResultsLocation)\$(ProjectNameSpace).UnitTests.xml"
ToolPath="$(NUnitToolPath)"
ContinueOnError="true" />
This works great. Now I'm trying to get those results to show in the Cruise Control web dashboard by doing a file merge with this command:
<publishers>
<merge>
<file>C:\CC\Project1\Code\UnitTestResults\Project1TestResults.UnitTests.xml</file>
</merge>
</publishers>
When I do this, the build still completes, but I get an exception in the Cruise Control console, which also show in the log:
2009-09-03 13:44:57,310 [Project1:DEBUG] Exception: System.Xml.XmlException: Name cannot begin with the '.' character, hexadecimal value 0x2E. Line 837, position 36.
Am I going about this wrong? How can I get my NUnit test results into the Cruise Control dashboard?

Try
<merge>
<files>
<string>C:\CC\Project1\Code\UnitTestResults\Project1TestResults.UnitTests.xml</string>
</files>
</merge>

The following works for me, though I'm using NAnt to trigger NUnit, not MSBuild:
<publishers>
<merge>
<files>
<file>C:\Projects\SomeApp\CI\TestResult.xml</file>
</files>
</merge>
<xmllogger />
</publishers>

Related

CruiseControl.NET 1.8.5 - Not creating msbuild-results xml file

I'm pretty new to build servers but have been asked by my employer to do some testing (because F5 is not a build process, as the excellent article by Jeff Atwood says). At this stage, I'm working on getting some sample builds and test reports up and running on a CruiseControl.NET server. So far, I've gotten a build up and running (the configuration file will need some tidying up before adding new builds/projects but the proof of concept is there) but the reporting is causing something of a headache.
The main report I'm looking for is for out NUnit tests and SpecFlow integration tests. The tests run fine (as I'm getting a sensible looking xml file generated) and am looking to merge that in to the main build results so that I can show the results of the NUnit/SpecFlowtests.
Whenever the build completes, the following is reported in the messages (in ViewFarmReport.aspx): "Failing Tasks : XmlLogPublisher "
This combined with the following error reported in the Windows application log (source - CC.Net)
2015-03-24 08:36:52,987 [Initech.SuperCrm-DEV] ERROR CruiseControl.NET [(null)] - Publisher threw exception: ThoughtWorks.CruiseControl.Core.CruiseControlException: Unable to read the contents of the file: C:\CCNet\BuildArtifacts\Initech.SuperCrm-DEV\msbuild-results-7c657954-2c3e-405f-b0f1-7da1299788fd.xml ---> System.IO.FileNotFoundException: Could not find file 'C:\CCNet\BuildArtifacts\Initech.SuperCrm-DEV\msbuild-results-7c657954-2c3e-405f-b0f1-7da1299788fd.xml'.
(company/application name "censored")
This leads me to suspect that the failure to merge in the msbuild results (which I believe CruiseControl.NET automatically scrapes since version... 1.5 or 1.6?) is preventing the NUnit results from being merged in.
There is no msbuild-results file in the BuildArtifacts folder, which does not surprise me as I do not believe my current msbuild configuration allows for xml based logging as I am using the ThoughtWorks.CruiseControl.MsBuild.dll logger.
According to the online documentation for CruiseControl.NET there is XML enabled custom logger: ThoughtWorks.CruiseControl.MsBuild.XmlLogger which can be used, however the download location for this logger: here
appears not to exist any more.
Can anyone say whether I'm thinking along the right lines here and what my options are?
For reference, here is my complete configuration:
<cruisecontrol xmlns:cb="urn:ccnet.config.builder">
<cb:define MSBuildPath="C:\Windows\Microsoft.NET\Framework\v4.0.30319" />
<cb:define WorkingBaseDir="C:\CCNet\Builds" />
<cb:define ArtifactBaseDir="C:\CCNet\BuildArtifacts" />
<cb:define MSBuildLogger="C:\Program Files (x86)\CruiseControl.NET\server
\ThoughtWorks.CruiseControl.MsBuild.dll" />
<cb:define NUnitExe="C:\Jenkins\Nunit\nunit-console.exe" />
<cb:define name="vsts_ci">
<executable>C:\Jenkins\tf.exe</executable>
<server>http://tfs-srv:8080/tfs/LEEDS/</server>
<domain>CONTOSO</domain>
<autoGetSource>true</autoGetSource>
<cleanCopy>true</cleanCopy>
<force>true</force>
<deleteWorkspace>true</deleteWorkspace>
</cb:define>
<project name="Initech.Libraries" description="Shared libraries used in all Initech projects"
queue="Q1">
<state type="state" directory="C:\CCNet\State"/>
<artifactDirectory>$(ArtifactBaseDir)\Initech.Libraries</artifactDirectory>
<workingDirectory>$(WorkingBaseDir)\Initech.Libraries</workingDirectory>
<triggers>
<intervalTrigger
name="continuous"
seconds="30"
buildCondition="IfModificationExists"
initialSeconds="5"/>
</triggers>
<sourcecontrol type="vsts">
<cb:vsts_ci/>
<workspace>CCNET_Initech.Libraries</workspace>
<project>$/InitechLibraries/Initech.Libraries</project>
</sourcecontrol>
</project>
<project name="Initech.SuperCrm-DEV" description="Initech.SuperCrm Application, Development
Version" queue="Q1">
<cb:define ArtifactDirectory="$(ArtifactBaseDir)\Initech.SuperCrm-DEV" />
<cb:define WorkingDirectory="$(WorkingBaseDir)\Initech.SuperCrm-DEV" />
<cb:define OutputDirectory="$(WorkingDirectory)\Initech.SuperCrm\bin\Debug" />
<cb:define ProjectFile="Initech.SuperCrm.sln" />
<cb:define NUnitLog="$(WorkingDirectory)\NunitResults.xml" />
<state type="state" directory="C:\CCNet\State"/>
<artifactDirectory>$(ArtifactDirectory)</artifactDirectory>
<workingDirectory>$(WorkingDirectory)</workingDirectory>
<triggers>
<!-- check the source control every X time for changes,
and run the tasks if changes are found -->
<intervalTrigger
name="continuous"
seconds="30"
buildCondition="IfModificationExists"
initialSeconds="5"/>
</triggers>
<sourcecontrol type="vsts">
<cb:vsts_ci/>
<workspace>CCNET_Initech.SuperCrm-DEV</workspace>
<project>$/InitechSuperCrm/SuperCrm/Initech.SuperCrm-DEV</project>
</sourcecontrol>
<tasks>
<exec>
<executable>C:\Program Files (x86)\DXperience 12.1\Tools\DXperience
\ProjectConverter-console.exe</executable>
<buildArgs>$(WorkingDirectory)</buildArgs>
</exec>
<msbuild>
<executable>$(MSBuildPath)\MSBuild.exe</executable>
<workingDirectory>$(WorkingDirectory)</workingDirectory>
<projectFile>$(ProjectFile)</projectFile>
<timeout>900</timeout>
<logger>$(MSBuildLogger)</logger>
</msbuild>
<exec>
<executable>$(NUnitExe)</executable>
<buildArgs>/xml=$(NUnitLog) /nologo $(WorkingDirectory)\$(ProjectFile)
</buildArgs>
</exec>
</tasks>
<publishers>
<buildpublisher>
<sourceDir>$(OutputDirectory)</sourceDir>
<useLabelSubDirectory>true</useLabelSubDirectory>
<alwaysPublish>false</alwaysPublish>
<cleanPublishDirPriorToCopy>true</cleanPublishDirPriorToCopy>
</buildpublisher>
<merge>
<files>
<file>$(NUnitLog)</file>
</files>
</merge>
<xmllogger logDir="C:\CCNet\BuildArtifacts\Initech.SuperCrm-DEV\buildlogs" />
<artifactcleanup cleanUpMethod="KeepLastXBuilds"
cleanUpValue="50" />
</publishers>
</project>
</cruisecontrol>
I've been tearing my hair while trying to figure this out, and I don't have much to begin with, so any help would be greatly appreciated.
After a prolonged period of banging my head against the wall, I seem to have finally found the solution (well solutions).
1) Kobush.Build.dll (https://www.nuget.org/packages/Kobush.Build/) can be used as the logger for MSBuild. Looking at the attributions in CruiseControl.NET's documentation, it appears to have been written by the same developer (but extended).
2) Some tweaks were needed due to the default location of the msbuild-report output. Because, by default, it was dumped to the buildartifacts folder then it is susceptible to being prematurely deleted.
I no longer clean the publish directory prior to copying (in the buildpublisher) and perform the merge and xmllogger portions of the publisher before artifact cleanup.
As a result, I now have msbuild and nunit output/results integrated in to the main build log and these can be consumed through the CruiseControl.NET dashboard.
There's probably a tidier way of handling this, but at the moment I'm just getting a proof of concept going.

Does CRuise Control use nAnt or MSbuild?

I am having issues understanding Cruise Control.
I would like to create a build automation in order to perform the build in my project. To do that I created the following entry in the ccnet.config file
<project name="My Web Release " description="Web config">
<workingDirectory>d:\GIT</workingDirectory>
<triggers/>
<sourcecontrol type="git">
<repository>GIT REPO</repository>
<branch>release-name</branch>
<autoGetSource>true</autoGetSource>
<fetchSubmodules>true</fetchSubmodules>
<executable>C:\Program Files (x86)\Git\cmd\git.exe</executable>
<tagOnSuccess>false</tagOnSuccess>
<commitBuildModifications>false</commitBuildModifications>
<commitUntrackedFiles>false</commitUntrackedFiles>
<tagCommitMessage> Build {0}</tagCommitMessage>
<tagNameFormat>Build-{0}</tagNameFormat>
<committerName>Build</committerName>
<committerEMail>build#build.com</committerEMail>
<workingDirectory>$(workingDirectory)\Sources\WEB</workingDirectory>
<timeout>600000</timeout>
</sourcecontrol>
<tasks>
<msbuild>
<executable>c:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe</executable>
<buildFile>BuildScript.xml</buildFile>
<targets>NewBuild</targets>
<logger>C:\Program Files (x86)\CruiseControl.NET\server\ThoughtWorks.CruiseControl.MsBuild.dll</logger>
</msbuild>
</tasks>
<publishers>
<xmllogger />
<artifactcleanup cleanUpMethod="KeepLastXBuilds" cleanUpValue="50" />
</publishers>
</project>
And I do have a BuildScript.xml file.
My question is:
Is this a nAnt or MSBUILD script?
I am asking because I am trying to follow the documentation but I get a lot of issues regarding unknown tasks and so on.
For instance, this:
<property name="configuration" value="CLOSED" />
Would generate a unknown "property" task.
I am looking at MSBuild documentation to use a Move task.
and I got to this line:
<move file="originPath" tofile="TargetPath"/>
But I get:
BuildScript.xml(18,3): error MSB4036: The "Move" task was not
found. C heck the following: 1.) The name of the task in the project
file is the same as the name of the task class. 2.) The task class is
"public" and implements the Microsoft.Build.Framework.ITask interface.
3.) The task is correctly declared w ith in the project file, or in the *.tasks files located in the "C:
\Windows\Microsoft.NET\Framework\v2.0.50727" directory.
What is driving me crazy is that it was working before we migrated to Cruise Control.
Is this being interpreted as nAnt or MSBuild? Any ideas on why I am getting these errors?
It looks like your mixing nant and msbuild, if it was msbuild it would look like
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" Tools="4.0">
<Target Name="Move">
<PropertyGroup>
<configuration>CLOSED</configuration>
</PropertyGroup>
<Move SourceFiles="Somefilefile" DestinationFolder="c:\temp"/>
</Target>
</Project>
So casing was an issue and that you need to specify the tools version as move is available from 4.0.

Selenium tests in MSBuild scripts

Is it possible to run Selenium scripts as a part of your deployment process in an MSBuild file? I'm looking for sample MSBuild snipets if people have them.
What's your test framework wrapper? If it's one of these supported, check out http://www.gallio.org/api/html/T_Gallio_MSBuildTasks_Gallio.htm
<UsingTask TaskName="Gallio" AssemblyFile="$(ProgramW6432)\Gallio\bin\Gallio.MsBuildTasks.dll" />
<Files Include="*Test*.dll" />
<Gallio
Files="#(Files)"
ReportTypes="xml"
ReportDirectory="$(Directory)"
/>

What in my CruiseControl.NET configuration is causing this exception?

In attempting to set up a build for a demo project I am working on, I received the following exception:
System.IO.DirectoryNotFoundException: Could not find a part of the path 'C:\Documents and Settings\Administrator\Local Settings\Temp\1bea7440-959c-4dd4-89ad-05dcd00e369c\ThoughtWorks.CruiseControl.MsBuild.dll'
Question: What don't I have configured correctly?
Below is my task block from my ccnet.config file:
<tasks>
<msbuild>
<executable>C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\MSBuild.exe</executable>
<workingDirectory>C:\CCWorkingDirectory\DemoApplication</workingDirectory>
<projectFile>DemoApplication.sln</projectFile>
<!--<buildArgs>/noconsolelogger /v:quiet
/p:Configuration=Debug
/p:ReferencePath="C:\Program Files\NUnit 2.4.7\bin"
</buildArgs>-->
<targets>ReBuild</targets >
<timeout>600</timeout >
<!--<logger>c:\Program Files\CruiseControl.NET\server\Rodemeyer.MsBuildToCCNet.dll</logger >-->
</msbuild>
</tasks>
You need to include ThoughtWorks.CruiseControl.MsBuild.dll in the working directory of your application.
So you need to put ThoughtWorks.CruiseControl.MsBuild.dll in C:\CCWorkingDirectory\DemoApplication
Here's a link about the MSBuild tag.
You could alternatively include it in the logger tag like so:
<logger>
C:\Program Files\CruiseControl.NET\server\
ThoughtWorks.CruiseControl.MsBuild.dll
</logger>

CruiseControl.net, msbuild, /p:OutputPath and CCNetArtifactDirectory

I'm trying to setup CruiseControl.net at the moment. So far it works nice, but I have a Problem with the MSBuild Task.
According to the Documentation, it passes CCNetArtifactDirectory to MSBuild. But how do I use it?
I tried this:
<buildArgs>
/noconsolelogger /p:OutputPath=$(CCNetArtifactDirectory)\test
</buildArgs>
But that does not work. In fact, it kills the service with this error:
ThoughtWorks.CruiseControl.Core.Config.Preprocessor.EvaluationException: Reference to unknown symbol CCNetArtifactDirectory
Documentation is rather sparse, and google und mainly offers modifying the .sln Project file, which is what I want to avoid in order to be able to manually build this project later - I would really prefer /p:OutputPath.
The CCNetArtifactDirectory is passed to the MSBuild by default, so you dont need to worry about it. MSBuild will place the build output in the "bin location" relevant to the working directory that you have specified.
<executable>c:\WINDOWS\Microsoft.NET\Framework\v3.5\MSBuild.exe</executable>
<workingDirectory>C:\data\projects\FooSolution\</workingDirectory>
<projectFile>FooSolution.sln</projectFile>
<buildArgs>/noconsolelogger /p:Configuration=Debug </buildArgs>
So in the above example your build output will be put in C:\data\projects\FooSolution[ProjectName]\bin\Debug. Should you want to output to a different location you may want to look at of the tag in CCNET.
<publishers>
<xmllogger />
<buildpublisher>
<sourceDir>C:\data\projects\FooSolution\FooProject\bin\Debug</sourceDir>
<publishDir>C:\published\FooSolution\</publishDir>
<useLabelSubDirectory>false</useLabelSubDirectory>
</buildpublisher>
</publishers>
This will allow you to publish your output to a different location.
You can use the artifact directory variable inside the MSBuild script itself. Here's an example of how I'm running FxCop right now from my CC.Net MSBuild script (this script is what CC.Net points to - there is also a "Build" target in the script that includes an MSBuild task against the SLN to do the actual compilation):
<Exec
Command='FxCopCmd.exe /project:"$(MSBuildProjectDirectory)\FXCopRules.FxCop" /out:"$(CCNetArtifactDirectory)\ProjectName.FxCop.xml"'
WorkingDirectory="C:\Program Files\Microsoft FxCop 1.35"
ContinueOnError="true"
IgnoreExitCode="true"
/>
Parameters like CCNetArtifactDirectory are passed to external programs using environment variables. They are available in the external program but they aren't inside CCNET configuration. This often leads to confusion.
You can use a preprocessor constant instead:
<cb:define project.artifactDirectory="C:\foo">
<project>
<!-- [...] -->
<artifactDirectory>$(project.artifactDirectory)</artifactDirectory>
<!-- [...] -->
<tasks>
<!-- [...] -->
<msbuild>
<!-- [...] -->
<buildArgs>/noconsolelogger /p:OutputPath=$(project.artifactDirectory)\test</buildArgs>
<!-- [...] -->
</msbuild>
<!-- [...] -->
</tasks>
<!-- [...] -->
</project>