posted on Wednesday, June 16, 2004 8:33 PM by joefield

CruiseControl.NET from Scratch - Version 1.0

Introduction

The idea of this article is to help you get started with CruiseControl.NET.  I’m assuming that you already know a bit about Continuous Integration and Test Driven Development and that you want to get up and running with CruiseControl.NET as quickly as possible.

I’m going to concentrate on setting up a system based on this environment:

·         .NET Framework v1.1

·         Visual Studio .NET 2003

·         Visual SourceSafe 6.0

 

This is a pretty common set-up at the moment.  However a lot of the ideas in this article are equally applicable to different versions of the CLR and Visual Studio .NET, and to different source control providers.

I’ve found that the many configuration options available in CruiseControl.NET can be a bit daunting so we are going to create a simple CruiseControl.NET setup by performing a series of steps.  You will end up with a working system which you can refine to meet your own needs.  Our configuration will consist of:

·         the CruiseControl.NET continuous integration server, initially running from the command prompt and later as a service

·         the Web Dashboard application which provides detailed information about completed builds

·         the CCTray system tray application, which runs on client machines and permits easy launch of the web application, forcing of builds etc

 

I have found these three applications to be excellent for the purposes of our development team.

Hardware

We are going to work with three machines:

·        the CruiseControl.NET build server, which will run the continuous integration server and the Web Dashboard – referred to in the configuration files that follow as "%buildserver%"

·        the server which hosts the SourceSafe database – referred to in the configuration files as "%sourceserver%"

·         a client machine which will run the CCTray system tray application and also view the CruiseControl.NET Web Dashboard using its browser

 

You can run everything on the same machine if you wish.

 

Software

To start with you’ll need the bits and pieces:

·         Visual Studio .NET 2003

·         Visual SourceSafe.  Version 6.0.

·         CruiseControl.NET.  Version 1.0 from: http://ccnet.thoughtworks.com.  It now comes with a neat installer (CruiseControl.NET-<version>-setup.exe)

·         NAnt for running build scripts.  Version 0.85-rc3 from: http://nant.sourceforge.net

·         NAntContrib for Visual SourceSafe support.  Version 0.85-rc3 from:  http://sourceforge.net/projects/nantcontrib

·         NUnit for adding test fixtures to Visual Studio .NET projects.  Version 2.2.0 from: http://www.nunit.org

 

The more recent versions of CruiseControl.NET can dispense with the need for NAnt, as they talk to SourceSafe directly for source retrieval and use Visual Studio .NET for the builds.  However I have not yet fully investigated this scenario, so we'll stick with NAnt for this article.

I’m also assuming that you have an IIS web server on your build server correctly configured to dish up ASP.NET pages.

Installation: Build Server

Your build server needs to have, at the least, a Visual SourceSafe client installation.  It does not, however, need a Visual Studio .NET installation as we will be using the NAnt solution task to build our project.

Create a directory on your build server to hold all the bits and pieces.  Mine is C:\Projects\CI (short for Continuous Integration).  In this directory:

·         Unzip NAnt to C:\Projects\CI\

·         Unzip NAntContrib to C:\Projects\CI\.  Then copy the contents of the nantcontrib-0.85-rc3\bin directory to the nant-0.85-rc3\bin directory.  This will enable NAnt to use the "vssget" task later on.

 

Now run the CruiseControl.NET installer on the build server and accept all the default settings except for the destination folder.  I like everything in the same place, so enter "C:\Projects\CI\CruiseControl.NET".

 

You now have a single directory on the build server containing your continuous integration environment.

 

Installation: Source Server

Your source control server needs a Visual SourceSafe server installation.

 

Installation: Client

Your client machine needs a Visual Studio .NET installation in order to create the project in this example.

 

It also needs NUnit 2.2 installed so that we can write some tests.

 

You will find the installer for the CCTray application inside the webdashboard\cctray folder in the build server installation.  Run this on the client, installing it to any destination folder you like.

 

Towards Our First Successful Build

We are going to run the continuous integration server from the command line at first – it's easier to see what's going on.  Open a command prompt window and navigate to C:\Projects\CI\CruiseControl.NET\server.  Run ccnet.exe.  You will see this output a bit like this:

[CruiseControl Server:Debug]: The trace level is currently set to debug...

[CruiseControl Server:Info]: Reading configuration file "C:\Projects\CI\CruiseControl.NET\server\ccnet.config"

[CruiseControl Server:Info]: No projects found

[CruiseControl Server:Info]: Registered channel: tcp

[CruiseControl Server:Info]: CruiseManager: Listening on url: tcp://192.168.0.1:21234/CruiseManager.rem

[CruiseControl Server:Info]: Starting CruiseControl.NET Server

 

Nice and neat – a big improvement on previous versions.  Starting in version 1.0 of CruiseControl.NET debug tracing is turned on by default, so even more information is displayed to help you get up and running.  The application is reading an XML file called ccnet.config, which at present has next to nothing in it.  But it is very happily starting and waiting for something to happen.  Unfortunately nothing will happen until we put something in ccnet.config.

We will modify ccnet.config file so that it contains two things:

·         a source code repository to examine for changes

·         a nant.exe to run and also a build file to run against

 

Once we’ve done this we’ll get our first successful build.

Modify ccnet.config

Leave ccnet.exe running and open ccnet.config in your favourite editor.  Whenever we change and save this file it will force a restart of the continuous integration server so we'll get immediate feedback.  Modify it to look like this:

<cruisecontrol>

  <project>

    <name>CITest</name>

    <triggers>

      <intervalTrigger seconds="60" buildCondition="ForceBuild" />

    </triggers>

    <sourcecontrol type="vss">

       <project>$</project>

       <username>ccnet</username>

       <password>ccnet</password>

       <ssdir>\\%sourceserver%\vss</ssdir>

    </sourcecontrol>

    <tasks>

      <nant>

        <executable>C:\Projects\CI\nant-0.85-rc3\bin\nant.exe</executable>

        <buildFile>cruise.build</buildFile>

        <targetList>

          <target>run</target>

        </targetList>

      </nant>

    </tasks>

  </project>

</cruisecontrol>

 

We have created a "project" element containing three other elements:

·         triggers – which tells CruiseControl.NET what sort of source code repository checks to perform.  We have asked that a build be forced every 60 seconds.  Later on we'll modify this to check the source code repository for changes.

·         sourcecontrol - which tells CruiseControl.NET which source code repository to monitor for changes

·         tasks -  which describes the NAnt binary and build script to run when changes are detected.  We don’t have the NAnt build script yet, but that doesn’t matter right now.

Let’s look at the file in detail.

Configure Visual SourceSafe

We have added a "sourcecontrol" element for Visual SourceSafe.  This is often the tricky part of CruiseControl.NET configuration.  You should note the following:

·         The "project" element is required.  I have initially set its value to “$” representing the root project in Visual SourceSafe.  We don’t have our own SourceSafe project yet.  When we do, we'll change this value.

·         The "username" and "password" elements are also required.  If they don’t refer to a valid SourceSafe user name with a valid password then CruiseControl.NET will freeze while displaying output which looks something like this:

 

...

...

[CITest:Debug]: Executing process D:\Program Files\Microsoft Visual Studio\VSS\win32\ss.exe history $ -R -Vd03/12/2005;22:00~03/12/2005;21:55 -Yccnet,badpassword -I-Y in C:\Projects\CI\CruiseControl.NET\server\CITest\WorkingDirectory

...

...

 

This is because (unseen by you) the SourceSafe command line application (ss.exe) is attempting to prompt you for a valid password!  You will need to break out of ccnet.exe and possibly kill ss.exe in task manager.  So set up a build user and password for CruiseControl.NET using SourceSafe Administrator, or input your own login credentials.

·         It’s a good idea to set the "ssdir" element, even though things should still work correctly without it as ss.exe will extract the server details from your build server’s copy of srcsafe.ini.  It appears to be able to locate this file by stepping up one directory in the hierarchy from where ss.exe is running!  The content of the element should be the name of the folder containing your database’s srcsafe.ini file.  Here the folder is shared as “vss” on the machine we’ve named %sourceserver%.

·         There is also an optional "executable" element which supplies ccnet with the path to ss.exe.  If you don’t supply one ccnet does some peeking in the registry to extract the path to your ss.exe, so I don’t personally bother with it.

 

Save the ccnet.config file.  Your console output should change immediately to something which contains lines like this.

 

 [CruiseControl Server:Debug]: Error loading buildfile.

[CruiseControl Server:Debug]:     Could not find file "C:\Projects\CI\CruiseControl.NET\server\CITest\WorkingDirectory\cruise.build".

 

Let's view our failure in the Web Dashboard.

The Web Dashboard

There is no initial configuration required for the Web Dashboard.  Simply navigate to http://%buildserver%/ccnet in a browser.  You’ll be able to see the CITest project and view details of the failure.

Now let’s fix that build file problem.

First Successful Build

We told CruiseControl.NET that:

·         there was a build file called “cruise.build”

·         the build file contained a target called “run”

 

This was all lies.  Let’s remedy the situation.  Create the cruise.build file in C:\Projects\CI\CruiseControl.NET\server\CITest\WorkingDirectory.  Mine looks like this:

<?xml version="1.0"?>

<project default="run">

  <target name="run">

  </target>

</project>

 

This should be enough to get us going.  The next time ccnet goes through a cycle I get this:

[CITest:Info]: No modifications detected.

[CITest:Info]: Build forced

[CITest:Info]: Building

[CITest:Info]: Build complete: Success

[CITest:Info]: Integration complete: 04/05/2005 22:44:14

 

Excellent!  Refresh the Web Dashboard and you’ll be able to gloat over your success.

CCNet System Tray Application

In fact I’m so pleased that I want to view my successful build another way.  Let’s set up the CCTray application.  CCTray uses .NET remoting to communicate with the build server.

We will need to tell CruiseControl.NET the URL for our particular project so that cctray can jump straight to that project's web page.  To do this add a "webURL" element to ccnet.config like this:

<cruisecontrol>

  <project name="CITest">

    <name>CITest</name>

<webURL>http://%buildserver%/ccnet/default.aspx?_action_ViewProjectReport=true&amp;server=local&amp;project=CITest</webURL>

...

...

I obtained this by viewing the CITest web page and pasting its URL into the config file, using &amp; in place of ampersands.

Now run the cctray.exe application on your client machine. (Tip: we add cctray.exe to our startup folder so that it is always running).

Double click on its system tray icon to bring up the application's main window then select Settings... from the File menu.

Now click on the Add... button to add our build server.  In the next dialog type the name of the build server in the input box and click on the Add Server button.  Select CITest from the projects list on the right and click OK.  You should now see our build server in the list on the main settings dialog.  Click OK.

Now the icon will go red if a failed build occurs.  You can also force a build by launching the main window and right clicking on the list entry for our project.  Cool!

What’s Next

Let’s summarise what we have achieved so far and what the final steps will be.  We have:

·         Configured the CruiseControl.NET continuous integration server (ccnet.exe) using the ccnet.config file.  This is nearly complete for the purposes of our project.  We are currently forcing a build every 60 seconds so that we don't have to modify our code in order to kick off a build.

·         Configured the CruiseControl.NET Web Dashboard so that it displays the results of our builds.

·         Configured the CruiseControl.NET system tray application (cctray.exe) so that remote clients are informed of build results and can view the status of their project in a browser.

 

Let's change the configuration so that CruiseControl.NET only runs a build when the source code repository changes.  It will then execute NAnt with our cruise.build file.  What we do inside the build file is up to us.  We are going to:

·         Clean the build directory for our project

·         Get the latest source code from the repository and compile it

·         Run tests

 

Remove Force Build

Modify the "triggers" element it so that it looks like this:

<cruisecontrol>

  <project name="CITest">

    <name>CITest</name>

    <webURL>http://localhost/ccnet</webURL>

    <triggers>

      <intervalTrigger seconds="60" />

    </triggers>

...

...

 

We have removed the force build.  From now on we will rely on checkins to start the integration process.

Add a Visual Studio .NET Project

Create a C# class library project with Visual Studio .NET called CITest.  Place it in your normal projects location – not under the CI directory.  Don’t add any code – just check that it builds.  Now, using Visual Studio, add your project to source control under the root SourceSafe project, so that we can reference its project path as "$/CITest" in our ccnet.config file.  (Tip:  When the "Add to SourceSafe Project" dialog pops up in Visual Studio, clear the "Project" text box completely, select the "$/" node and press OK.  A project named CITest will then be correctly added under the root.  If you type "CITest" in this box, you'll end up with a project called $/CITest/CITest!)

Now modify the "project" element within the "sourcecontrol" element of our ccnet.config file as follows:

<cruisecontrol>

  <project name="CITest">

...

...

    <sourcecontrol type="vss">

      <project>$/CITest</project>

...

...

 

You should still have a successful build!

Now we are going to modify the cruise.build file to clean the build directory, get the source and compile it.

Backtracking to NAnt

We are going to run NAnt directly against our cruise.build file for a while.  Remember that this is all that CruiseControl.NET does – so when we've got it all working smoothly we can just plug it back again.  In the meantime we will get a bit more help with diagnostics from the output produced by NAnt.

It is very useful, whenever you're experiencing problems with CruiseControl.NET, to run NAnt directly against your build file, so this technique may well save you a lot of time somewhere down the line.  if you're really having problems try running it with the "–verbose" option.

Create a batch file called startnant.bat in the C:\Projects\CI directory and insert the following line:

nant-0.85-rc3\bin\nant.exe -buildfile:CruiseControl.NET\server\CITest\WorkingDirectory\cruise.build

This will execute NAnt against our cruise.build file.  Stop CruiseControl.NET and execute startnant.bat.  You will see this:

 

NAnt 0.85 (Build 0.85.1932.0; rc3; 16/04/2005)

Copyright (C) 2001-2005 Gerry Shaw

http://nant.sourceforge.net

 

Buildfile: file:///C:/Projects/CI/CruiseControl.NET/server/CITest/WorkingDirectory/cruise.build

Target framework: Microsoft .NET Framework 1.1

Target(s) specified: run

 

 

run:

 

 

BUILD SUCCEEDED

 

Total time: 0.1 seconds.

 

Now modify cruise.build so that it deletes and creates a "Source" directory in which we are going to get and build our source.  It will now look like this:

<?xml version="1.0" ?>

<project default="run">

  <target name="run" depends="clean">

  </target>

  <target name="clean">

    <delete dir="Source" failonerror="false" />

    <mkdir dir="Source" />

  </target>

</project>

 

When you run startnant.bat it will delete the Source directory (if it exists) then create it.  Now add a target which uses the vssget task from NAntContrib to get the source from SourceSafe:

<?xml version="1.0" ?>

<project default="run">

  <target name="run" depends="get">

  </target>

  <target name="get" depends="clean">

    <vssget username="ccnet"

            password="ccnet"

            localpath="Source"

            recursive="true"

            replace="true"

            writable="false"

            dbpath="\\%sourceserver%\vss\srcsafe.ini"

            path="$/CITest"/>

  </target>

  <target name="clean">

    ....

</project>

 

The "srcsafe.ini" at the end of the "dbpath" attribute isn't required if you're using a UNC path to access your source control server.  Check that you're getting the source correctly by running startnant.bat.  At the end of the build the CITest directory should contain a copy of the source.

Finally add a target to build the solution file:

<?xml version="1.0" ?>

<project default="run">

  <target name="run" depends="build">

  </target>

  <target name="build" depends="get">

    <solution configuration="debug" solutionfile="Source\CITest.sln" />

  </target>

  <target name="get" depends="clean">

    ...

    ...

</project>

 

Notice that each time we modify the file we change the dependencies.  The targets will be run by NAnt in the following order:

·         clean

·         get

·         build

 

Later on we'll run a test target.  Note that I haven't used any NAnt properties in my build file.  I leave this for you to play with later.

When you run startnant.bat you should now see:

NAnt 0.85 (Build 0.85.1932.0; rc3; 16/04/2005)

Copyright (C) 2001-2005 Gerry Shaw

http://nant.sourceforge.net

 

Buildfile: file:///C:/Projects/CI/CruiseControl.NET/server/CITest/WorkingDirectory/cruise.build

Target framework: Microsoft .NET Framework 1.1

Target(s) specified: run

 

clean:

 

   [delete] Deleting directory 'C:\Projects\CI\CruiseControl.NET\server\CITest\WorkingDirectory\Source'.

    [mkdir] Creating directory 'C:\Projects\CI\CruiseControl.NET\server\CITest\WorkingDirectory\Source'.

 

get:

 

   [vssget] Getting '$/CITest' to 'C:\Projects\CI\CruiseControl.NET\server\CITest\WorkingDirectory\Source'...

 

build:

 

 [solution] Starting solution build.

 [solution] Building 'CITest' [Debug] ...

 

run:

 

 

BUILD SUCCEEDED

 

Total time: 1.1 seconds.

Now restart ccnet and cctray.  You should still have a successful build.  If not, view the NAnt log (by clicking on the “View Build Log” link in the Web Dashboard) to find out the reason.

Once you have everything running smoothly, try breaking the build by checking out a file from the CITest project, adding a compilation error and checking it in again.  CruiseControl.NET will detect the modification and the build will fail.  Fix it!

NAnt and Assembly References

In previous versions of NAnt there were often problems when referencing third party assemblies installed in the GAC.  These seem to be resolved in the latest version (at least in the case of NUnit) so the simplest thing for us to do in order to be able to write some tests is:

·         add a reference to the nunit.framework assembly in the CITest directory by using the ".NET" tab "Add Reference" dialog.

 

Add a Test

Modify your Class1.cs to look something like this:

using System;

using NUnit.Framework;

 

namespace CITest

{

  /// <summary>

  /// Summary description for Class1.

  /// </summary>

  [TestFixture]

  public class Class1

  {

    public Class1()

    {

      //

      // TODO: Add constructor logic here

      //

    }

 

    [Test]

    public void ThisTestWillDefinitelyFail()

    {

      Assert.Fail("This test fails and I expect Cruise Control to display this message");

    }

  }

}

 

Now modify the cruise.build file one last time to run any test fixtures present in your dll.  Here is the final version of cruise.build, with the modifications highlighted:

<?xml version="1.0" ?>

<project default="run">

  <target name="run" depends="test">

  </target>

  <target name="test" depends="build">

    <nunit2>

      <formatter type="Xml" />

      <test assemblyname="Source\bin\debug\CITest.dll" />

    </nunit2>

  </target>

  <target name="build" depends="get">

    <solution configuration="debug" solutionfile="Source\CITest.sln" />

  </target>

  <target name="get" depends="clean">

    <vssget username="ccnet"

            password="ccnet"

            localpath="Source"

            recursive="true"

            replace="true"

            writable="false"

            dbpath="\\desktop\vss\srcsafe.ini"

            path="$/CITest"/>

  </target>

  <target name="clean">

    <delete dir="Source" failonerror="false" />

    <mkdir dir="Source" />

  </target>

</project>

 

I’ve added a target which runs NUnit against our assembly.  I’ve specified the “Xml” formatter, as CruiseControl.NET expects XML output.

Check in the code and run startnant.bat to check the cruise.build file.  You should see output ending like this:

...

...

   [nunit2] <failure>

   [nunit2] <message><![CDATA[This test fails and I expect Cruise Control to display this message]]></message>

   [nunit2] <stack-trace><![CDATA[   at CITest.Class1.ThisTestWillDefinitelyFail() in c:\Projects\CI\CruiseControl.NET\server\CITest\WorkingDirectory\Source\Class1.cs:line 22

   [nunit2] ]]></stack-trace>

   [nunit2] </failure>

   [nunit2] </test-case>

   [nunit2] </results>

   [nunit2] </test-suite>

   [nunit2] </results>

   [nunit2] </test-suite>

   [nunit2] </results>

   [nunit2] </test-suite>

   [nunit2] </test-results>

   [nunit2]

 

BUILD FAILED

 

C:\Projects\CI\CruiseControl.NET\server\CITest\WorkingDirectory\cruise.build(6,6):

Tests Failed.

 

Total time: 1.7 seconds.

 

Exactly what we want.  Your ccnet build should fail, and you will see the test failure displayed in the web application.  Now modify Class1 by adding the [Ignore] attribute like this:

    [Ignore("I wanna successful build")]

    [Test]

    public void ThisTestWillDefinitelyFail()

    {

      Assert.Fail("This test fails and I expect Cruise Control to display this message");

    }

 

Sit back and relax.  Your next build will succeed.  You will be able to see the ignored test in the Web Dashboard output.  We’re done!

Now that we have a working continuous integration system there are lots of possible refinements.  I won’t attempt to cover them all, but here are some candidates in no particular order of priority.

Running the CruiseControl.NET Service

An easy one this – just stop running ccnet.exe and start the Windows Service instead.  The output that we have been viewing via the console is still logged to a file called ccnet.log in the CruiseControl.NET\server directory.

Adding Visual Studio Projects

Don't forget that as you add more projects to your solution you will need to add a new "test" element to cruise.build, otherwise your tests won't be run!

Also if you want to use application configuration files (as many people do when using NUnit) you will need to reference them within your "test" element like this:

  <test assemblyname="CITest\bin\debug\CITest.dll" appconfig="CITest\bin\debug\CITest.dll.config" />

 

Adding Multiple CruiseControl Projects

Very handy this – multiple projects handled by the same build server – and/or multiple build servers managed by a single Web Dashboard.  See the CruiseControl.NET documentation for more detail.

Merging NAnt Output

For more control over the output from your build script send it to files and combine the files with the CruiseControl.NET log using a merge task.  This involves changing the "formatter" element in the cruise.build file so that it sends output to files:

<formatter type="Xml"

    usefile="true"

    extension=".xml" />

 

and adding a publishers element to the ccnet.config file so that it merges these files into the log:

...

    <publishers>

      <merge>

        <files>

          <file>Source\bin\debug\*-results.xml</file>

        </files>

      </merge>

      <xmllogger />

    </publishers>

  </project>

</cruisecontrol>

 

Note also that we have added a xmllogger publisher.  This is the default publisher used by CruiseControl.NET and is automatically used if you don't create a publishers element in the ccnet.config.  Once, however, you start to specify publishers you need to include it.  It also needs to be after the merge element.

Bootstrapping NAnt

In our team we maintain two NAnt build scripts.  The first one just cleans the build directory and gets the latest source from the repository.  Included in the latest source is the second build script, which is invoked from the first.  The second script compiles the source and runs the tests.

The advantage of this approach is that we can maintain the second build script as a solution item and modify it (for example by adding a new "test" element) whenever we add a new project to the solution.  When the solution is checked in CruiseControl.NET will automatically perform the modified build.

Summary

Any effort you invest in setting up CruiseControl.NET is repaid many times over, and I hope that this article has helped you on your way.

Comments

# re: CruiseControl.NET from Scratch

Tuesday, July 06, 2004 5:28 AM by Ganesh
How about configuring CruiseControl for StarTeam.
I have a problem. CruiseControl does not detect modifications.

# StarTeam and CruiseControl.NET

Tuesday, July 06, 2004 8:16 PM by Joe Field
I don't have a StarTeam installation at present - does CruiseControl.NET display the command line that it's sending to StarTeam (like it does with the vss history command)? If so try running the same command "stand-alone" from the command line - you may get some output which gives you some help. CruiseControl.NET sometimes says it doesn't detect modifications when in fact it's receiving unexpected output from the tool. Hope this helps.

# re: CruiseControl.NET from Scratch

Tuesday, July 06, 2004 10:04 PM by Dr. Neil
Nice work Joe. I'll be going through this in the next couple of days & let you know how how it works out.

# re: CruiseControl.NET from Scratch

Thursday, August 05, 2004 1:19 PM by Rusty
Thanks so very much! Your article helped a great deal. I am up and running with a small, manageable test project and CruiseControl.net. Now all I have to do is integrate about twelve projects on independent release cycles but, hell, that's the easy part!

# re: CruiseControl.NET from Scratch

Monday, August 09, 2004 7:39 PM by Joe Field
Glad it was a help Rusty. Let me know if you have any ideas for improvements / new articles and good luck with the 12 projects!

# re: CruiseControl.NET from Scratch

Tuesday, August 31, 2004 10:38 AM by JoeD
Exactly what I needed - on my way!

# re: CruiseControl.NET from Scratch

Tuesday, August 31, 2004 4:06 PM by Harry Chou
Thank you for writing this useful article.

# re: CruiseControl.NET from Scratch

Tuesday, September 14, 2004 4:10 AM by VA
Thanks u so much. U saved me tons of time.

# re: CruiseControl.NET from Scratch

Saturday, October 02, 2004 10:52 PM by Vito
Yeah!! Fantastic. Thank you for the informative article.

# re: CruiseControl.NET v0.7 from Scratch

Saturday, December 04, 2004 1:05 AM by Scott Shepherd
Joe, there are just a critical element missing that left me befuddled. I found the solution so I thought I would share it with others struggling to get the sample to work.

It has to do with one of the items in the cruise.build file:

Don't forget to append the "\srcsafe.ini" file name onto the end of the dbpath= attribute or you will get a silly error that begins like this "Failed to open database The Source Safe database path...not found"

Once I figured that out, it worked like a champ!! Thanks for the info!

# re: srcsafe.ini appended to dbpath in vssget task

Saturday, December 04, 2004 3:56 PM by Joe Field
Thanks for that Scott. It's an interesting one this. My guess is you're using a non UNC path. If you're using a UNC path you don't need to add the srcsafe.ini. If you aren't it's required! I'll update the article to reflect this. Cheers.

# re: CruiseControl.NET v0.7 from Scratch

Sunday, January 09, 2005 3:00 PM by Stephen Seymour
Thanks a lot, Joe. I followed your instructions and had very little problems, none of which were your fault. This was a very helpful article, indeed.

FYI, it might help you out to create a "ThirdParty" folder in your source control to which you add all third-party dlls...such as NUnit. Then you can reference the dlls in this folder (or subfolders you place within it) by directly browsing to them when adding a reference in Visual Studio. Plus, this makes it easier when upgrading to a newer version of the third-party dlls because you don't have to rely on your entire team to go and get them at roughly the same time.

Thanks again,

~Steve Seymour

# re: CruiseControl.NET v0.7 from Scratch

Tuesday, January 11, 2005 4:51 PM by Modena
Hey Joe....great article...answered a lot of questions for me...

One question though...If CCNET detects a change in the Projects SourceSafe and downloads the new code and runs the NAnt build file...Why use NAnt Contrib do the same thing?

# CCNET vs NAntContrib

Tuesday, January 11, 2005 6:27 PM by Joe Field
Hi Modena - good question

Originally CCNET couldn't get your source, but now the vss sourcecontrol element has an "autogetsource" attribute which will get the source when a change is detected. This however has its limitations. The main one is that it doesn't clean the build directory, which I like to do (as you can see from the article).

Similarly CCNET now has a devenv builder which you can use instead of the nant one. The drawback here is that you need Visual Studio .NET installed on your build server.

But if you want quick and easy it is in theory possible not to use NAnt at all. I have meant for a while to write an article about this, which will give me a chance to properly test out these features.

Cheers.

# Third Party Folders

Tuesday, January 11, 2005 6:32 PM by Joe Field
Hi Steve

Yes it is definitely a good idea not to have duplicate versions of third party assemblies scattered around! In the interests of simplicity I didn't mention this in the article.

On our team we use SourceSafe shares to accomplish this. Personally I prefer this to having a directory sitting above the projects containing the assemblies. The idea being that you can always grab a project from its root directory and compile it.

However in practice when there are multiple inter-project dependencies one tends to end up grabbing whole solutions anyway in which case the "ThirdParty" folder makes just as much sense.

So horses for courses really...

# re: CruiseControl.NET v0.7 from Scratch

Tuesday, January 11, 2005 7:23 PM by Modena
Regarding the Web aspect, when I unzip the CCNET v0.7 download package, I get 2 directories: "web" and "webdashboard"

is the WebDashboard folder the main site? and is the web folder the project folder?

# WebDashboard

Wednesday, January 12, 2005 4:52 AM by Joe Field
Hi Modena

The WebDashboard is a different app used for monitoring multiple projects. For setting up a single project you only need the "web" folder.

# Changing CCNET Port

Wednesday, January 12, 2005 3:46 PM by Modena
By default CCNET runs on port 21234...how do you specify a different port?

Thanks for all the help Joe!

# re: CCNET vs NAntContrib

Wednesday, January 12, 2005 4:23 PM by Modena
Regarding the Cleaning the Build Directory....The way I handle that is in my NAnt Build File I have a "Clean" Target and the "Run" target depends on it....so when CCNET downloads the new source....it runs NAnt which cleans the Build Directory and recompiles the source

# re: Changing CCNET Port

Thursday, January 13, 2005 6:47 PM by Joe Field
You'll find what you need in ccnet.exe.config...

# CCNET 0.8 out...

Thursday, January 20, 2005 8:26 PM by Modena
CCNET 0.8 out...

# re: CruiseControl.NET v0.7 from Scratch

Wednesday, January 26, 2005 10:13 AM by Modifications not detected
Very helpful information. Good job!

I've one issue, the CC server is working great when I force a build. However, no changes are ever detected. I've run the SS "history" command, and it does show the files that have changed. When CC runs it always comes back with "no modifications detected."

Any ideas or suggestions would be greatly appreciated.

Thanks,

Dan.

# re: CruiseControl.NET v0.7 from Scratch

Thursday, March 03, 2005 2:59 PM by Chris H
Recieving the following error and have gotten no response from the NAnt team...


C:\BuildProcess>startnant.bat

C:\BuildProcess>"NAnt 0.84\bin\nant.exe" -buildfile:cruise.build
NAnt 0.84 (Build 0.84.1455.0; net-1.0.win32; release; 12/26/2003)
Copyright (C) 2001-2003 Gerry Shaw
http://nant.sourceforge.net

Buildfile: file:///C:/BuildProcess/cruise.build
Target(s) specified: run

clean:

[delete] Deleting directory C:\BuildProcess\CITest.
[mkdir] Creating directory C:\BuildProcess\CITest.

get:

[vssget] Put $/CITest to CITest

build:

[solution] Starting solution build.

BUILD FAILED

INTERNAL ERROR

System.NullReferenceException: Object reference not set to an instance of an object.
at NAnt.VSNet.Reference..ctor(Solution solution, ProjectSettings ps, XmlElement elemReference, SolutionTask solutionTask, String outputDir)
at NAnt.VSNet.Project.Load(Solution sln, String projectPath)
at NAnt.VSNet.ProjectFactory.LoadProject(Solution sln, SolutionTask slnTask, TempFileCollection tfc, String outputDir, String path)
at NAnt.VSNet.Solution.LoadProjects()
at NAnt.VSNet.Solution..ctor(String solutionFileName, ArrayList additionalProjects, ArrayList referenceProjects, TempFileCollection tfc, SolutionTa
sk solutionTask, WebMapCollection webMappings, FileSet excludesProjects, String outputDir)
at NAnt.VSNet.Tasks.SolutionTask.ExecuteTask()
at NAnt.Core.Task.Execute()
at NAnt.Core.Target.Execute()
at NAnt.Core.Project.Execute(String targetName, Boolean forceDependencies)
at NAnt.Core.Project.Execute()
at NAnt.Core.Project.Run()

Please send bug report to nant-developers@lists.sourceforge.net.

Total time: 0.2 seconds.

# Good Stuff - Minor update needed

Thursday, March 17, 2005 6:35 PM by John
Good stuff - tremendous help - thanx! BTW, you need to update your triggers tag in this article based on the la