Configuring CruiseControl.net project directory - cruisecontrol.net

CruiseControl.net creates (by default) for each project a subdirectory under: c:\Program File\CruiseControl.NET\server
How can I change that? (it's such a bad idea to mix data with program files...)
I found a way to configure the artifacts directory per project, but that's not quite it (it's merely a subdirectory of the project directory).

Set the project's working and artifact directory and you're done. They default to:
[ccnet-install-dir]\[project-name]\WorkingDirectory
[ccnet-install-dir]\[project-name]\Artifacts.
If you e.g. set these directories to...
[projects-dir]\[project-name]\WorkingDirectory
[projects-dir]\[project-name]\Artifacts
... you can safely remove the [ccnet-install-dir]\[project-name] subtree (You will loose your project build history then).
So your configuration will look like this:
<project name="foo">
[...]
<workingDirectory>C:\projects\foo\WorkingDirectory</workingDirectory>
<artifactDirectory>C:\projects\foo\Artifacts</artifactDirectory>
[...]
</project>

I have CC.NEt not installed here, and I have atm no access to my build-server at work, but if I remember well, you should find 2 configuration files in your c:\Program Files\CruiseControl.NET folder.
ccnet.exe.config and ccservice.exe.config.
The first configuration file is used when you run CC.NET using the console app, the second one is used when you start CC.NET as a service.
In those files, you should find a configuration-setting which points to the location where the configuration-file(s) that describe the build-process for your projects can be found.
edit:
In the ccservice.exe.config file, you'll find a key in the appSettings section which is called ccnet.config. Change the value of this key to the path where you want to put the ccnet.config file.
If this key is not present, you can add it:
<appSettings>
<!-- Without this appSetting ccservice will look for ccnet.config in its own directory. -->
<add key="ccnet.config" value="D:\CCNetConfigFiles\ccnet.config"/>
</appSettings>
This is how I've done it:
I've changed the ccnet.config appSetting in the ccservice.exe.config file, so that CruiseControl.NET searches for the ccnet.config file in a different location instead of the standard location. (As described above). (I understand that you do not want to do this ?)
I've changed the ccnet.config file itself, so that it looks like this:
<!DOCTYPE cruisecontrol [
<!ENTITY project1 SYSTEM "file:D:\CCNETConfigFiles\project1\project1buildconfig.xml.config">
<!ENTITY project2 SYSTEM "file:D:\CCNETConfigFiles\project2\project2buildconfig.xml.config">
<!ENTITY project3 SYSTEM "file:D:\CCNETConfigFiles\project3\project3buildconfig.xml.config">
]>
<cruisecontrol>
&project1;
&project2;
&project3;
</cruisecontrol>
By doing this, I can have each project configuration in its own file, and I can put each project-configuration in its own directory.
Then, I just have to make sure that in each project config-file, I remove the cruisecontrol tags, because otherwise the ccnet.config file wouldn't validate against the schema.

Probably not the answer you're waiting for, but could still be interesting: we're using about twenty build machines with about fifty different builds. Because indeed it's not a good idea to mix data with program files, we decided to put our ccnet installation in source control. Each server has its own configuration file in that directory (also in source control) and a local batch file or short cut starting ccnet specifies which configuration file is used. This means that local data (the build logs) are mixed with data that is in perforce (ccnet binaries/configuration files), but we have accepted that situation. Hope this helps.
Regards,
Sebastiaan

Related

Include referenced assembly's configuration in cspkg

I have an executable that I want to be deployed together with my Azure web role. The executable has a configuration file that needs to be included as well.
I tried adding a reference to the executable's project in my web role project, which made the exe file appear in the bin folder of the cspkg, but not the configuration file.
How can I get the configuration file to be included as well?
It seems wrong to include it directly as a content file in the web role project because this file is a build artifact (app.config gets renamed to .config.exe during build).
Thanks!
In an early SDK they added the concept of Role Content folders, or folders you could point to in the service definition file and say anything in this folder, add it to the package and deploy it with the role. If you look at the schema for the Service Definition you'll see these listed on the both the web and worker roles schemas. You can manually add this and point to any location on the local system and anything in that directory will be picked up and included.
<WebRole name="SimpleWeb" vmsize="Small">
...
<Contents>
<Content destination="ConsoleApp">
<SourceDirectory path="c:\src\SimpleWebContent\ConsoleApp\BuildOutput" />
</Content>
</Contents>
</WebRole>
For example, you could point to the output directory of the build for your executable so that anything that is generated by your build for that executable would be included. You can set the destination directory in relation to the app root, but the tricky part is the source directory. Note in my example above the full path is provided. The documentation says that you can use a relative path, but I tried many combinations and the behavior seemed very quirky. The complete path does work.
The VS SDK tools didn't expose this until SDK 1.7 and it's still not very good. Phil Hoff did a blog post on it called "Add Files to your Windows Azure Package using Role Content Folders". Note that when you use this method of adding the files you won't see the content elements appear in your service definition. They get auto injected at package time. If you are doing this as part of a build process that may not happen since VS tooling is doing the injection, but to be fair I didn't try calling cspack directly to see if having the content elements included in the service definition file actually packaged those or not. Also, I found that just adding a new folder and just having files under that folder didn't seem to work. I had to actually add the files by name there, which seemed wrong. I did hack the .ccproj file to use a wildcard on the folder include, which did work, but also seemed like a hack to me.

What is the name of the web role .config file with SDK 2.2

I have a web role in which I have extended the RoleEntryPoint to do some work that is outside of the scope of the web site. As part of the RoleEntryPoint.Run() my code is required to read from the .config using ConfigurationManager.
While this is a little unusual, using SDK 1.8 I was able to make this work by ensuring that my package included a [The name of my project].dll.config file.
Now that I have upgraded to SDK 2.2 when I try to use .AppSettings or .GetSection() the values are always null, which leads me to believe it is unable to find my file.
I have tried deploying a Worker Role and the .config file still follows the same name pattern that I'm currently using.
I have also tried naming the file WaIISHost.exe.config.
I am aware that ideally this configuration should be included in the .csfg file, but my questions is does anyone know what I should be calling my config file?
UPDATE:
With the help of this question, I now know that the name of the config file it is reading from is E:\base\x64\WaIISHost.exe.Config, but I don't know why this has changed or what I can to overide this.
After much investigation and trial an error I finally have a solution.
The name of the file is still required to be [The name of my project].dll.config, but you need to make sure that this file is in your approot\bin\ directory of your package.
I believe my initial problem was caused by the Copy to Output Directory property being changed to Do Not Copy, although I'm unsure how this happened. If you find yourself in a similar situation you can just add a file with the correct name to your project and set the Copy to Output Directory to be Copy Always.
Once I'd done that however I realised I had another problem. I needed the .config file to have had the config transformations run over it, which this didn't do. To fix this I updated the .ccproj file to have the following:
<PropertyGroup>
<!-- The first two of these targets are what is defined in the base SDK 2.2 targets file. When we upgrade we may need to look reassess this. -->
<CopyRoleFilesDependsOn>
CopyWebRoleFiles;
CopyWorkerRoleFiles;
CopyWebConfigToBin;
</CopyRoleFilesDependsOn>
</PropertyGroup>
<Target Name="CopyWebConfigToBin">
<!-- We need to copy the transformed Web.config to the bin directory so that the RoleEntryPoint has access to the config settings.-->
<Message Text="Copy %(WebRoleReferences.OutputDir)Web.config tp %(WebRoleReferences.OutputDir)\bin\BackOffice.UI.dll.config" Importance="high" />
<Copy SourceFiles="%(WebRoleReferences.OutputDir)Web.config" DestinationFiles="%(WebRoleReferences.OutputDir)bin\[Name of project].dll.config" />
</Target>
This adds an extra target which waits until all of the other files have been copied to the appropriate directory and then picks up the web.config and puts a copy in the bin directory with the correct name.
Are you able to put the config values into the Azure config file (the .cscfg) rather than using the .config file? You can read the values from the cscfg via the RoleEnvironment.GetConfigurationSettingValue static method.
This page explained why it's called WaIISHost.exe.Config and where you can put it in your project.
http://azure.microsoft.com/blog/2010/12/02/new-full-iis-capabilities-differences-from-hosted-web-core/
Like knightpfhor mentioned, you can also use [AssemblyName].dll.config to put these configuration too. It depends on the assembly name of your project, you can check property of your web role project.

AjaxMin not working on Azure site

I am using Microsoft's AjaxMin to minify javascript on my website, which is hosted by Azure. I am using a BuildTask to automatically minify javascript at run time. This build task is specified in the .csproj file.
The process is working on my local environment, however, it does not work when I deploy to my Azure site. The azure site throws 404: file not found errors, when i try to reference the minified version of .js files.
Is it possible to use build tasks on an Azure site? Is there anything I am missing? I have made sure not to include the .min.js files in source control as this (http://www.asp.net/ajaxlibrary/AjaxMinQuickStart.ashx) tutorial suggests, but I am wondering if there is anything specific to Azure that I need to set up.
Thanks!
I've got this working properly in my projects. I'll tell you how I did it, though this may not be the simplest or most straightforward way.
Before we get started, it's helpful to be able to check if your minified files are included in the Azure deployment package without actually deploying. It's pretty easy to do. The .cspkg file is actually a zip-formatted file, so you can open it with any zip archiver. (I like to use 7Zip for this because the right-click -> Open Archive command doesn't require you to rename the file, but you could use Windows Explorer, WinRAR, etc.) Inside the .cspkg you'll see another large file with a .cssx extension. That's a zip file too. Inside of the .cssx you'll find a sitesroot folder with a subdirectory for each website you're deploying, which will contain all your actual website files. So you can poke around in there and see what files are being deployed to Azure.
First, try editing the project file for your web project (the one that contains all the Javascript/CSS files). You can use Notepad, or in Visual Studio right-click the project, select "Unload Project", then right-click again and select "Edit ". Inside the project file, insert a section like this:
<ItemGroup>
<!-- Copy over all the minified CSS & JS to the output directory-->
<Content Include="**\*.min.css" />
<Content Include="**\*.min.js" />
</ItemGroup>
Then reload the project, repackage it, and see if your files are included in the .cspkg file. If they are, then you're done.
If not, there are a couple other things to check. Your minification might not be running at the right build stage. My minification target looks like this:
<Target Name="PrepWebApp" Condition="$(Configuration)=='Release'" AfterTargets="AfterBuild">
If that's still not working and your Web Role has multiple Sites and/or Virtual Applications in it, it's possible that the packaging steps are not running for all of the sites. So when you go to package your project for deployment to Azure, it may still not be running the minification step (along with the web.config transformations, and some other things). If that's the case, see this blog post for a way to fix it.
Just in case that blog post goes away, I'll copy the most relevant bit here. You would put this in the .ccproj file for your web role (with appropriate bits changed to match your project structure):
<PropertyGroup>
<!-- Inject the publication of "secondary" sites into the Windows Azure build/project packaging process. -->
<CoreBuildDependsOn>
CleanSecondarySites;
PublishSecondarySites;
$(CoreBuildDependsOn)
</CoreBuildDependsOn>
<!-- This is the directory within the web application project directory to which the project will be "published" for later packaging by the Azure project. -->
<SecondarySitePublishDir>azure.publish\</SecondarySitePublishDir>
</PropertyGroup>
<!-- These SecondarySite items represent the collection of sites (other than the web application associated with the role) that need special packaging. -->
<ItemGroup>
<SecondarySite Include="..\WebApplication1\WebApplication1.csproj" />
<SecondarySite Include="..\WebApplication2\WebApplication2.csproj" />
</ItemGroup>
<Target Name="CleanSecondarySites">
<RemoveDir Directories="%(SecondarySite.RootDir)%(Directory)$(SecondarySitePublishDir)" />
</Target>
<Target Name="PublishSecondarySites" Condition="'$(PackageForComputeEmulator)' == 'true'
Or '$(IsExecutingPublishTarget)' == 'true' ">
<!--
Execute the Build (and more importantly the _WPPCopyWebApplication) target to "publish" each secondary web application project.
Note the setting of the WebProjectOutputDir property; this is where the project will be published to be later picked up by CSPack.
-->
<MSBuild Projects="%(SecondarySite.Identity)" Targets="Build;_WPPCopyWebApplication" Properties="Configuration=$(Configuration);Platform=$(Platform);WebProjectOutputDir=$(SecondarySitePublishDir)" />
The build task will run in Visual Studio when you build the project. You need to make sure that the minified files are also being deployed to Azure.
I'm guessing that perhaps because the item is being generated at build-time that it's not part of the project itself, and is this ignored by the deployment step.
Please check that the deployment system being used will include all the script files and not just the ones that are in the project itself.

How do I change the location of CruiseControl log files?

The server where CruiseControl.NET is already installed is running out of disk space.
Is there a simple way of moving the CruiseControl logs to another drive?
Found it here.. http://confluence.public.thoughtworks.org/display/CCNET/Xml+Log+Publisher
The Xml Log Publisher is used to create the log files used by the CruiseControl.NET Web Dashboard, so if you don't define an section the Dashboard will not function correctly.
You should place the in the section, after any File Merge Tasks, in your Project Configuration Block.
Examples
Minimalist example:
<xmllogger />
Full example:
<xmllogger logDir="c:\myproject\buildlogs" />
Regardless of moving logs somewhere else, you should also use Artifact Cleanup Publisher to delete older logs. It is done on a per-project base, usually set up to keep X last build logs or logs from X last days. Also, storing project's workingDirectory and artifactDirectory on a separate, large drive is usually a good idea.

Why Does CruiseControl.NET need to be restarted after GetCcNetConfigFiles?

CruiseControl.NET service needs to be restarted to pick up changes in the projects configuration files.
I find this very annoying, not sure if it's a bug or it's the way it works.
Is there any way to overcome this issue in people's experience?
If your projects are separated in a different file from ccnet.config, then you need to restart the service unless you touch the actual ccnet.config.
We use ENTITY with SYSTEM file reference in ccnet.config for our projects, so we're in the same boat. I'm happy to pay the price for easier project maintenance, as it's easy to script a restart:
net stop CCService
net start CCService
IISRESET
If you wanted to completely automate this, and had your projects under source control, then you could trigger an update and restart whenever your project files are touched.
There was a bug in CC.Net prior to 1.4.4 if you were using a pre-processor include it did not reload the configuration when an included ccnet.config file was modified.
That was a bug that I reported and it is fixed in CC.Net 1.4.4 and greater.
Also, keep in mind that if a build is running and there is a change to the configuration it will not take place until that build is in an idle state.
How are you updating your config files? By hand? Mine always recognizes and adjusts. Is your config file in source control and designed to pull it down and replace the file? This for me requires a kick. How I ended up fixing it was have my project pull it down to a seperate folder. THen I call ccnet.exe -validate on it to make sure it is well formed, then I copy it over ontop of the current config file. CC.NET recognizes the changes and loads in the new config
Exceptions: If cc.net is currently running a project, it will not recognize the changes till that project has completed.
If your ccnet.config has errors, it will not ever recognize the changes and keep running the old version it has stored in memory. (However when CC.NET does restart it will try to parse the error filled config and choke.
Hope this helps!!
Do you mean you are using linked files, that is the ccnet.config file has links to the independent project files.
If so then they are not picked up, it's mentioned in the documentation that it doesn't watch the sub-files.
Internally we have modified our CruiseControl.net so that our ccnet.config is optionally a directory - and we can drop shortcuts to our project config files into that directory. We put watches on the directory, the files or shortcuts in the directory and all of the targets of the shortcuts. That means we have our project config files in ClearCase and just drop a shortcut into the ccnet.config directory.
I've just spent half a day or so moving from 1.2 to 1.4.2 dropping our changes into the new version for our internal use. We don't own our code, our client does and so it has to stay internal :(
I have never experienced this. Whenever I change the configuration files, the CruiseControl.NET service seems to automatically re-read them.
I'm using Version 1.3 of CC.NET.
Update:
In the service's config file (ccservice.exe.config), there is a setting to enable/disable watching the ccnet.config file for changes:
<add key="WatchConfigFile" value="true"/>
Make sure this is set to true.

Resources