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

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.

Related

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.

Nant delete task doesn't delete files post msbuild

Using Nant 0.92 (and previously 0.85 with same consequence)
I'm trying to call the delete task in NAnt to remove all files except the .dll file after calling msbuild (see the script below .. I'm referring to the delete in the "build" target). The delete task does not seem to execute.
The initial delete task works fine, and behaves as expected, removing all files from the specified build directory. The second delete task, after the compile however doesn't work.
I've tried just deleting everything (not using the exclude tag), tried explicitly setting failonerror and verbose to true. None of these make a difference. I've also tried using sleep to stop the process prior to the delete task, in case something in msbuild was not releasing the files in time for a delete. I've tried putting the delete into a separate target, still no luck.
The command obviously works prior to calling msbuild, and it works after msbuild if trying to delete from a directory other than the msbuild output target (i.e. copy the output files, then delete relevant files).
I'm sure that this is too fundamental a problem to be a bug, but I thought I'd ask anyway. Of course I'll use the workaround in the mean time of just copying the files to a different location delete what I don't need then move appropriately, but I'm curious about this.
I suspect, that unless this behaviour is by design (although I can find nothing in the NAnt documentation to suggest it is), then perhaps the msbuild process is locking the output files until NAnt process completes? This is my best guess. Further insights would be appreciated.
EDIT: also, if I explicitly set the \OutputPath switch of msbuild, then I don't have the same problem. It only appears that when the default OutputPath is used is the problem created.
NAnt build file:
<?xml version="1.0" encoding="utf-8" ?>
<project name="Reports.TestBench.PreBuild" default="postbuild.cleanup" basedir="." xmlns="http://nant.sourceforge.net/release/0.86-beta1/nant.xsd">
<property name="nant.settings.currentframework" value="net-4.0" />
<property name="project.StandardReports" value="${project::get-base-directory()}\Reports.StandardReports\Palladium.Reports.StandardReports.csproj" />
<property name="output.Dir" value="${project::get-base-directory()}\bin\debug\"/>
<property name="build.Type" value="debug"/>
<!--Deletes the pre-existing build files-->
<target name="clean">
<delete>
<fileset basedir="${output.Dir}">
<include name="*.*" />
</fileset>
</delete>
</target>
<!--Builds the projects to the specified build directory-->
<target name="build" depends="clean" description="Build the Palladium Reports Standard Reports application">
<msbuild project="${project.StandardReports}">
<arg value="/p:Configuration=${build.Type}" />
<!--arg value="/p:OutputPath=${path::get-full-path(buildDir.Client)}\Reports" /-->
<arg value="/t:Rebuild" />
</msbuild>
<delete failonerror="true" verbose="true">
<fileset basedir="${output.Dir}">
<include name="*.*" />
<exclude name="Palladium.Reports.StandardReports.dll" />
</fileset>
</delete>
</target>
</project>
Summary of NAnt output showing build success with no further messages:
[msbuild] Build succeeded.
[msbuild] 0 Warning(s)
[msbuild] 0 Error(s)
[msbuild]
[msbuild] Time Elapsed 00:00:03.19
BUILD SUCCEEDED
Total time: 3.5 seconds.
Try poking into NAnt source code - most likely the msbuild task creates an MSBuild engine and does not force it to close the files afterwards. Although looking at the MSDN docs, I don't really see a way to do it - MSBuild constructs lack a Dispose() function. There's a finalizer on classes such as ProjectInstance, so one could force it release the file handles by running in an application domain and closing the whole domain afterwards - that's quite a bit of work.

CruiseControl.Net error: Unknown plugin for <msbuild>

I'm trying to get CruiseControl.Net working with MSBuild (this is my first exposure to CruiseControl.Net). I thought I'd done the configuration correctly, however I just get the following error message when starting up:
[cc]Jun-22 20:02:55 Main - error setting config file on controller
net.sourceforge.cruisecontrol.CruiseControlException: error configuring project MyProject
at *SNIP*
Caused by: net.sourceforge.cruisecontrol.CruiseControlException: Unknown plugin for: <msbuild>
at *SNIP*
[cc]Jun-22 20:02:55 Main - error configuring project MyProject
As far as I can work out, this would appear to indicate that I'm missing the MSBuild plugin, however all documentation that I can find indicates that the MSBuild plugin has been included with CruiseControl.Net since version 1.0
I'm using the latest binary release (v 2.8.3)
Here is my config xml:
<project name="MyProject">
<listeners>
<currentbuildstatuslistener file="logs/${project.name}/status.txt"/>
</listeners>
<bootstrappers></bootstrappers>
<modificationset quietperiod="10">
<filesystem folder="C:\snip\main"/>
</modificationset>
<schedule interval="60">
<msbuild>
<executable>C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\MSBuild.exe</executable>
<workingDirectory>C:\snip\main</workingDirectory>
<projectFile>MyProject.sln</projectFile>
<buildArgs>/p:Configuration=Debug /v:diag</buildArgs>
<targets>Build;Test</targets>
<timeout>900</timeout>
<logger>C:\Program Files\CruiseControl.NET\server\ThoughtWorks.CruiseControl.MsBuild.dll</logger>
</msbuild>
</schedule>
<log />
<publishers />
</project>
Any advice on how I can troubleshoot this would be much appreciated.
Aggg - it appears that I have unwittingly downloaded CruiseControl, instead of CruiseControl.Net (and to make things even more confusing I was looking at CruiseControl.Net documentation)

Where is sun-appserv-ant.jar for Glassfish v3

Where is sun-appserv-ant.jar in Glassfish v3
I have created a small sample EJB project and I want to use ant to deploy the application to Glassfish v3.
Ive spent a lot of time on google trying to achieve this and all ant samples seem to refer to a jar file called "sun-appserv-ant.jar" which is supposed to be located in the modules directory of the application server install, however, I cannot find it anywhere, nor can I seem to find the reason why, or if there is even an ant based alternative.
Thanks
The sun-appserv-ant.xml file was not brought forward with v3.
You are not completely stuck though.
You can read about the Ant exec task, which you can use to trigger asadmin commands.
If you are very adventurous, you may want to investigate the bp-project framework that is used by the sample projects that ship with the Java EE 6 SDK.
You can get a peek at the bp-project framework by looking at the code in the glassfish-samples repository.
You should add the glassfish-ant-tasks module through the GlassFish Update Tool
After much agony I found an example of how to use the V3.x ant tools here
The downside, for non-French-speakers, is that it's in French. The upside is that the Java parts are still in Java.
From what I can tell, the Ant tasks now differ significantly from what is documented by Sun (Oracle):
You must use the Glassfish server update tool to get the glassfish-ant-tasks module.
This will cause the file *glassfish_dir*/lib/ant/ant-tasks.jar to be downloaded. That must be included on your classpath
Define an as-ant-init target in your build.xml
<target name="as-ant-init">
<taskdef name="sun-appserv-deploy"
classname="org.glassfish.ant.tasks.DeployTask"
classpath="${build-lib}/ant-tasks.jar" />
<taskdef name="sun-appserv-undeploy"
classname="org.glassfish.ant.tasks.UndeployTask"
classpath="${build-lib}/ant-tasks.jar" />
<taskdef name="sun-appserv-component"
classname="org.glassfish.ant.tasks.ComponentTask"
classpath="${build-lib}/ant-tasks.jar" />
<taskdef name="sun-appserv-admin"
classname="org.glassfish.ant.tasks.AdminTask"
classpath="${build-lib}/ant-tasks.jar" />
<taskdef name="sun-appserv-redeploy"
classname="org.glassfish.ant.tasks.RedeployTask"
classpath="${build-lib}/ant-tasks.jar" />
<taskdef name="sun-appserv-start-server"
classname="org.glassfish.ant.tasks.StartServerTask"
classpath="${build-lib}/ant-tasks.jar" />
<taskdef name="sun-appserv-stop-server"
classname="org.glassfish.ant.tasks.StopServerTask"
classpath="${build-lib}/ant-tasks.jar" />
</target>
Write the deployment target. The rules are similar to what's in the documentation, EXCEPT
A. Remove references to the <server> element that was used in older versions.
B. All of the attributes that would have been attached to <server> in the older version of the API are now attached directly to the containing element, such as <sun-appserv-deploy>, like so:
<target name="deploy">
<sun-appserv-deploy
user="${glassfish.admin-user}"
passwordfile="${glassfish.passwordfile}}"
host="${glassfish.host}"
port="${glassfish.admin-port}"
installDir="${asinstalldir}"
upload="true" >
<component
file="${dist.warfile}"
name="My application"
contextroot="${glassfish.context-root}" />
</sun-appserv-deploy>
</target>

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>