CruiseControl.NET use project name in project config - cruisecontrol.net

Is there any way to use the project name in the project config in CruiseControl.NET ?
I tried ${project.name} based on other posts which doesn't work.
<cruisecontrol xmlns:cb="urn:ccnet.config.builder">
<cb:define BuildArtifactsMainDir="D:\CCNet\BuildArtifacts\"/>
<project name="MyProject">
<artifactDirectory>$(BuildArtifactsMainDir)${project.name}</artifactDirectory>
<tasks>
<exec>
<executable>C:\Windows\System32\robocopy.exe</executable>
<buildArgs>D:\${project.name} F:\${project.name}</buildArgs>
<buildTimeoutSeconds>600</buildTimeoutSeconds>
<successExitCodes>0,1,3,4,8,16</successExitCodes>
</exec>
</tasks>

I don't think there's a parameter for project name. You can use scopes instead.
<cruisecontrol xmlns:cb="urn:ccnet.config.builder">
<cb:define BuildArtifactsMainDir="D:\CCNet\BuildArtifacts\"/>
<cb:scope ProjectName="MyProject">
<project name="$(ProjectName)">
<artifactDirectory>$(BuildArtifactsMainDir)$(ProjectName)</artifactDirectory>
...
</project>
</cb:scope>

Related

msbuild+wix : how to get heatdirectory to use defineconstants's variable?

hello everybody : my first post !
i am trying to get a wixproj using heatdirectory to take its source directory using visualstudio's "Define Constants" feature, in which i define a constant SourceBinaries=c:\someproject\bin\release.
The purpose is to use the same wixproj/setup for several projects and automate the whole with TFS-Build...
however, the Directory Tag never gets the SourceBinaries's value.
here's the xml code :
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
blah..
<OutputName>ProjectSetup</OutputName>
blah..
</PropertyGroup>
<PropertyGroup>
<OutputPath>bin\$(Configuration)\</OutputPath>
<IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
<DefineConstants>SourceBinaries=c:\someproject\bin\release\</DefineConstants>
</PropertyGroup>
<ItemGroup>
blah..
</ItemGroup>
<Import Project="$(WixTargetsPath)" />
<Target Name="BeforeBuild">
<HeatDirectory NoLogo="$(HarvestDirectoryNoLogo)"
Directory="$(SourceBinaries)"
PreprocessorVariable="var.SourceBinaries"
SuppressAllWarnings="$(HarvestDirectorySuppressAllWarnings)"
SuppressSpecificWarnings="$(HarvestDirectorySuppressSpecificWarnings)"
ToolPath="$(WixToolPath)"
TreatWarningsAsErrors="$(HarvestDirectoryTreatWarningsAsErrors)"
TreatSpecificWarningsAsErrors="$(HarvestDirectoryTreatSpecificWarningsAsErrors)"
VerboseOutput="$(HarvestDirectoryVerboseOutput)"
AutogenerateGuids="$(HarvestDirectoryAutogenerateGuids)"
GenerateGuidsNow="$(HarvestDirectoryGenerateGuidsNow)"
OutputFile="ProductFiles.wxs"
SuppressFragments="$(HarvestDirectorySuppressFragments)"
SuppressUniqueIds="$(HarvestDirectorySuppressUniqueIds)"
Transforms="Transforms.xsl"
ComponentGroupName="ProductFiles"
DirectoryRefId="INSTALLLOCATION"
KeepEmptyDirectories="false"
SuppressCom="%(HarvestDirectory.SuppressCom)"
SuppressRootDirectory="true"
SuppressRegistry="%(HarvestDirectory.SuppressRegistry)">
</HeatDirectory>
blah..
</Target>
<Target Name="AfterBuild">
blah..
</Target>
</Project>
whatever i tried lead me to "Error The "HeatDirectory" task was not given a value for the required parameter "Directory".
can somebody help me resolving this ?
thanks in advance...
Didier
I think your main source of confusion is that the variables defined in the <DefineConstants> element only work for the .wxs files, but they will not work in the .wixproj file itself.
To fix this you could do something like:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
blah..
<OutputName>ProjectSetup</OutputName>
blah..
</PropertyGroup>
<PropertyGroup>
<OutputPath>bin\$(Configuration)\</OutputPath>
<IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
<SourceBinaries>c:\someproject\bin\release</SourceBinaries>
<DefineConstants>SourceBinaries=$(SourceBinaries)</DefineConstants>
</PropertyGroup>
<ItemGroup>
blah..
</ItemGroup>
<Import Project="$(WixTargetsPath)" />
<Target Name="BeforeBuild">
<HeatDirectory NoLogo="$(HarvestDirectoryNoLogo)"
Directory="$(SourceBinaries)"
PreprocessorVariable="var.SourceBinaries"
SuppressAllWarnings="$(HarvestDirectorySuppressAllWarnings)"
SuppressSpecificWarnings="$(HarvestDirectorySuppressSpecificWarnings)"
ToolPath="$(WixToolPath)"
TreatWarningsAsErrors="$(HarvestDirectoryTreatWarningsAsErrors)"
TreatSpecificWarningsAsErrors="$(HarvestDirectoryTreatSpecificWarningsAsErrors)"
VerboseOutput="$(HarvestDirectoryVerboseOutput)"
AutogenerateGuids="$(HarvestDirectoryAutogenerateGuids)"
GenerateGuidsNow="$(HarvestDirectoryGenerateGuidsNow)"
OutputFile="ProductFiles.wxs"
SuppressFragments="$(HarvestDirectorySuppressFragments)"
SuppressUniqueIds="$(HarvestDirectorySuppressUniqueIds)"
Transforms="Transforms.xsl"
ComponentGroupName="ProductFiles"
DirectoryRefId="INSTALLLOCATION"
KeepEmptyDirectories="false"
SuppressCom="%(HarvestDirectory.SuppressCom)"
SuppressRootDirectory="true"
SuppressRegistry="%(HarvestDirectory.SuppressRegistry)">
</HeatDirectory>
blah..
</Target>
<Target Name="AfterBuild">
blah..
</Target>
</Project>
Above, we're creating a new <SourceBinaries> element with the path to the directory. This custom element can then be used as a variable in the rest of the .wixproj file. We then use this value to populate the SourceBinaries constant that is used in the .wxs files.
In conclusion, in the <HeatDirectory> element:
the Directory attribute gets its value from <SourceBinaries>
The PreProcessorVariable attribute gets its value from <DefineConstants> (or other variables available to .wxs files like project references)
You could use the HarvestDirectory target as described here http://wixtoolset.org/documentation/manual/v3/msbuild/target_reference/harvestdirectory.html.

How can I set define multiple parameters in CCNet?

I am working in CCNet version 1.4, and I am having difficulty getting the parameters I want defined in a clean manner. In my example, I want 6 total projects as (3 solutions in 2 branches). I defined a generic project that could incorporate all 6 possibilities based on choice of 8 variables. When it's a trunk project, 4 of the variables should be one thing. When it's a branch project, the 4 variables should be another thing. The other 4 variables are dependent on which solution I want to build.
In my attempt below, I put the 4 trunk variables in one define block and the 4 release variables in another block. I also have a define block for each of the solutions.
<cb:define name="ProductBuildProject">
<project name="$(ProjectName)" queue="Common">
<category>Main Builds</category>
<sourcecontrol type="multi">
<sourceControls>
<cb:svn-sourcebuild-checkout BranchPath="$(BranchPath)" MainSourcePath="$(MainSourcePath)" />
</sourceControls>
</sourcecontrol>
<modificationDelaySeconds>10</modificationDelaySeconds>
<labeller type="defaultlabeller">
<prefix><cb:LabelPrefix/></prefix>
<incrementOnFailure>true</incrementOnFailure>
</labeller>
<triggers>
<intervalTrigger name="continuous" seconds="900" buildCondition="IfModificationExists"/>
</triggers>
<tasks>
<nant>
<executable>&nant-path;</executable>
<baseDirectory><cb:LocalKeywordLabPath/>\<cb:MainSourcePath/></baseDirectory>
<buildArgs>-v -D:deployServer=<cb:DeployServer/></buildArgs>
<buildFile><cb:BuildFileName/></buildFile>
<targetList>
<target><cb:BuildTargetName/></target>
</targetList>
<buildTimeoutSeconds>600</buildTimeoutSeconds>
</nant>
</tasks>
<publishers>
<merge>
<files>
<file><cb:LocalKeywordLabPath/>\<cb:MainSourcePath/>\<cb:UnitTestOutputPath/></file>
</files>
</merge>
&publishers-common-block;
</publishers>
<externalLinks/>
</project>
</cb:define>
<cb:define name="TrunkBuildParameters">
<cb:define name="LocalKeywordLabPath"><cb:keywordlab-trunk-local/></cb:define>
<cb:define name="BranchPath"><cb:trunk-path/></cb:define>
<cb:define name="LabelPrefix">1.1.0.</cb:define>
<cb:define name="DeployServer">smwtlkwlab01n</cb:define>
</cb:define>
<cb:define name="ReleaseBranchBuildParameters">
<cb:define name="LocalKeywordLabPath"><cb:keywordlab-release-local/></cb:define>
<cb:define name="BranchPath"><cb:releaseBranch-path/></cb:define>
<cb:define name="LabelPrefix">1.1.100.</cb:define>
<cb:define name="DeployServer">smwdvkwlab03n</cb:define>
</cb:define>
<cb:define name="KeywordLabWebParameters">
<cb:define name="MainSourcePath">Source\Presentation</cb:define>
<cb:define name="BuildFileName">KeywordLab.Web.build</cb:define>
<cb:define name="BuildTargetName">automated-with-webdeploy</cb:define>
<cb:define name="UnitTestOutputPath">KeywordLab.Web.UnitTest\bin\Release\KeywordLab.Web.UnitTest.trx</cb:define>
</cb:define>
<cb:define name="KeywordLabWebMvcParameters">
<cb:define name="MainSourcePath">Source\UI</cb:define>
<cb:define name="BuildFileName">KeywordLab.Web.Mvc.build</cb:define>
<cb:define name="BuildTargetName">automated-with-webdeploy</cb:define>
<cb:define name="UnitTestOutputPath">KeywordLab.Web.Mvc.Tests\bin\Release\KeywordLab.Web.Mvc.Tests.trx</cb:define>
</cb:define>
<cb:define name="KeywordLabServiceParameters">
<cb:define name="MainSourcePath">Source\Service</cb:define>
<cb:define name="BuildFileName">KeywordLab.build</cb:define>
<cb:define name="BuildTargetName">automated</cb:define>
<cb:define name="UnitTestOutputPath">KeywordLab.UnitTest\bin\Release\KeywordLab.UnitTest.trx</cb:define>
</cb:define>
Finally, I try to define the 6 projects each by referencing the define block for the trunk or release build and the correct define block for the solution.
<!--KeywordLab Web-->
<cb:ProductBuildProject>
<cb:define name="ProjectName">KeywordLab Web (1N)</cb:define>
<cb:TrunkBuildParameters/>
<cb:KeywordLabWebParameters/>
</cb:ProductBuildProject>
<!--KeywordLab Web Mvc-->
<cb:ProductBuildProject>
<cb:define name="ProjectName">KeywordLab Web Mvc (1N)</cb:define>
<cb:TrunkBuildParameters/>
<cb:KeywordLabWebMvcParameters/>
</cb:ProductBuildProject>
<!--KeywordLab Service-->
<cb:ProductBuildProject>
<cb:define name="ProjectName">KeywordLab Service (1N)</cb:define>
<cb:TrunkBuildParameters/>
<cb:KeywordLabServiceParameters/>
</cb:ProductBuildProject>
<!--KeywordLab Web-->
<cb:ProductBuildProject>
<cb:define name="ProjectName">Release Branch (3N) - KeywordLab Web</cb:define>
<cb:ReleaseBranchBuildParameters/>
<cb:KeywordLabWebParameters/>
</cb:ProductBuildProject>
<!--KeywordLab Web Mvc-->
<cb:ProductBuildProject>
<cb:define name="ProjectName">Release Branch (3N) - KeywordLab Web Mvc</cb:define>
<cb:ReleaseBranchBuildParameters/>
<cb:KeywordLabWebMvcParameters/>
</cb:ProductBuildProject>
<!--KeywordLab Service-->
<cb:ProductBuildProject>
<cb:define name="ProjectName">Release Branch (3N) - KeywordLab Service</cb:define>
<cb:ReleaseBranchBuildParameters/>
<cb:KeywordLabServiceParameters/>
</cb:ProductBuildProject>
This isn't working and I'm hoping that someone can point out what I'm doing wrong. When I try to load this config, the error I receive is:
[CCNet Server:ERROR] INTERNAL ERROR: Reference to unknown symbol LabelPrefix
As you can see in TrunkBuildParameters and ReleaseBranchBuildParameters, I define LabelPrefix in both, and all 6 projects reference one or the other of these define blocks. I then try to reference this in the block of the project. This is apparently not a valid way of defining a variable for use by projects. Could someone please tell me what I'm doing wrong or perhaps a better way to do this at all?
I'd suggest using the Validator supplied with cruisecontrol to see what the final parsed config file is, to check if you've missed anything.
Having said that, what I usually do is the other way around. I define commonly used config blocks and then write out the project config with only a few lines. Perhaps you'll consider that clean enough?

MSBuild: Permanently Change PropertyGroup Property of a Project

I was hoping to find a way to set a value in my csproj file during my build to a value. Is there a task in MSBuild that I can use to set a property permanently to a value? In the example below, can I set CustomValue = Yes permanently?
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
.....
<CustomValue>XXXX</CustomValue
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids></ProjectTypeGuids>
<SccProjectName>SAK</SccProjectName>
<SccLocalPath>SAK</SccLocalPath>
<SccAuxPath>SAK</SccAuxPath>
<SccProvider>SAK</SccProvider>
</PropertyGroup>
You can use the XmlPoke task to do that. It seems a little odd to be altering projects this way though. Alternatively, you can set up a tiny import file,
<!-- in your main project file, right below the PropertyGroup -->
<Import
Condition="Exists('Custom.props')"
Project="Custom.props"
/>
Then dynamically create this property file, as,
<?xml version="1.0" encoding="utf-8"?>
<Project
xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
ToolsVersion="4.0">
<PropertyGroup>
<CustomValue>True</CustomValue>
</PropertyGroup>
</Project>
You can either use XmlPoke on just this .props file, or use WriteLinesToFile to create the entire file. This secondary file wouldn't need to be checked into source control, the condition on the import makes the project functional when the file doesn't exist.
The XmlPoke task would look like this,
<XmlPoke
XmlInputPath="./Custom.props"
Namespaces="<Namespace Prefix='x'
Uri='http://schemas.microsoft.com/developer/msbuild/2003'/>"
Query="//x:PropertyGroup/x:CustomValue/#Value"
Value="True"
/>

How to run a task before updating source files?

I need to run a task in CruiseControl .NET before checking for modification in source control. I mean this task should be the very first thing that CruiseControl will always do. I see
<prebuild> section in cc.config, but it is for running tasks before building a solution, so it is not exactly what I need.
Prebuild DOES fire before the source control get. It comes after the source control block but still fires first. Here's an example I've been using:
<cb:define subversionpath="c:\Program Files\Subversion\bin\svn.exe"
/>
<cb:define name="svn50">
<executable>$(subversionpath)</executable>
<workingDirectory>D:\Projects\B50\Source</workingDirectory>
<trunkUrl>svn://machineName/branches/B_50/Source</trunkUrl>
<autoGetSource>true</autoGetSource>
</cb:define>
<project name="StreamlineCheckBuild" queue="B50">
<triggers>
<intervalTrigger seconds="180" />
</triggers>
<sourcecontrol type="svn">
<cb:svn50/>
<deleteObstructions>true</deleteObstructions>
<forceUpdate>true</forceUpdate>
</sourcecontrol>
<prebuild>
<exec>
<executable>$(subversionpath)</executable>
<buildArgs>cleanup</buildArgs>
<baseDirectory>D:\Projects\B50</baseDirectory>
</exec>
</prebuild>
<tasks>
...
</tasks>
</cruisecontrol>
Use batch file as proxy for the version control utility, eg. svn.bat:
echo do stuff
"c:\program files\Subversion\svn.exe" %*
Use executable atrribute to point to the bach file.

Cruise control merging?

I had successfully extracted the compilation log present in my IDE into some one xml file very well. So in order to merge it I had mentioned in my ccnet.config file inside the publisher task using the <merge>
section.
But when I force my build, I am able to get the output.xml file correctly but an
error is thrown in ccnet.config window that it is unable to merge as this file is currently used by some other process.
Please see below:
[VSAT:ERROR] Publisher threw
exception:
ThoughtWorks.CruiseControl.Core.CruiseC
ontrolException: Unable to read the
contents of the file: C:
\ThreePartition\outp ut.xml --->
System.IO.IOException: The process
cannot access the file 'C:\ThreeP
artition\output.xml' because it is
being used by another process.
Can you suggest any method by which merging can be done successfully?
I have pasted the whole ccnet.config file below.
<project name="VSAT">
<sourcecontrol type="filtered">
<sourceControlProvider type="filesystem">
<repositoryRoot>C:\ThreePartition</repositoryRoot>
<autoGetSource>true</autoGetSource>
<ignoreMissingRoot>false</ignoreMissingRoot>
</sourceControlProvider>
<exclusionFilters>
<pathFilter>
<pattern>C:\ThreePartition\wrSbc750gx_ThreePartition\**</pattern>
</pathFilter>
<pathFilter>
<pattern>C:\ThreePartition\*.txt</pattern>
</pathFilter>
<pathFilter>
<pattern>C:\ThreePartition\*.xml</pattern>
</pathFilter>
</exclusionFilters>
</sourcecontrol>
<triggers>
<intervalTrigger name="continuous" seconds="240"
buildCondition="IfModificationExists" />
</triggers>
<tasks>
<nant>
<executable>C:\Nant-0.85\bin\NAnt.exe</executable>
<buildFile>nant.build</buildFile>
</nant>
</tasks>
<publishers>
<merge>
<files>
<file>C:\ThreePartition\output.xml</file>
</files>
</merge>
<xmllogger logDir="C:\Program Files\CruiseControl.NET\server\DF2.0-CI
\Logfiles" />
<email from="BuildAdmin#server.com"
mailhost="smtp.servermail.com" includeDetails="TRUE">
<users>
user name="Maddy" group="buildmaster"
address="Mymail#server.com"/>
</users>
<groups>
<group name="buildmaster" notification="always"/>
<group name="developers" notification="change"/>
</groups>
</email>
</publishers>
</project>
</cruisecontrol>
I had just placed the publishers section below for the better view
<publishers>
<merge>
<files>
<file>C:\ThreePartition\output.xml</file>
</files>
</merge>
<email from="BuildAdmin#server.com" mailhost="smtp.server.com" includeDetails="TRUE">
<users>
<user name="Maddy" group="buildmaster" address="Maddy.#server.com"/>
</users>
<groups> <group name="buildmaster" notification="always"/>
<group name="developers" notification="change"/>
</groups>
</email>
Some ideas:
Eliminate other obvious applications that would be writing to that file: other CCNet projects, other CCNet instances (e.g. are you maybe running the service and something from the command line?), or perhaps your source control.
If you're not attached to NAnt, try MSBuild and see if you get the same error. If all you're doing is compiling, you can pass the .sln or .csproj as a parameter directly to MSBuild.
Make sure you're on the latest version of CCNet - they regularly publish what I would consider fairly major bug fixes regularly.
What is says: the question is which process has open your xml while CC.net is trying to merge -- perhaps Process Explorer could be useful? Perhaps it works if you copy the xml output to a separate file and merge that.

Resources