Source Code Control (RSS)

Source Code Control

Troubleshooting CruiseControl.Net and Completed Unit Tests

CruiseControl.Net Update

So, I explained yesterday how I got CruiseControl.Net installed as part of my quest to institute Continuous Integration in my development project. After I published yesterday's entry, I found that I hadn't done one crucial thing.

Getting The Latest  Version From Subversion Before The Build

My build kept happening every time I "committed" a new version of a source file to Subversion, but my changes weren't showing up in the CruiseControl.Net build. I soon realized my mistake, I needed to modify the the NAnt build files with a couple of new <target>'s, one for getting the latest version from source control, and one for calling the "update" target and then the "build" target. I could have just added the "update" to the "build" target, but I may want to just "build" the current snapshot rather than always getting the latest version. So now I have the following for my main (D:\VirtualCellar\default.build) file. I found this page helpful in setting up CruiseControl.Net with Subversion.

<?xml version="1.0"?>
<project name="VirtualCellar" default="build" basedir=".">
  <property name="debug" value="true"/>
  <property name="build.deploy" value="release"/>
  <property name="build.business" value="Lorengo.VirtualCellar.Business"/>
  <property name="build.business.tests" value="Lorengo.VirtualCellar.Business.Tests"/>

  <sysinfo/> 

  <target name="build" description="compiles projects">
    <nant buildfile="${build.business}/default.build" target="build"/>
    <nant buildfile="${build.business.tests}/default.build" target="build"/>

    <copy todir="${build.deploy}/bin" file="${build.business}/bin/debug/${build.business}.dll"/>
  </target>

  <target name="update" description="Gets the latest version from source control">
    <exec basedir="." program="d:\program files\subversion\bin\svn.exe" commandline="update" />
  </target>

  <target name="buildLatest" description="Builds the latest version from source control" depends="update,build" />
</project>

The "buildLatest" target depends the "build" target which depends on the "update" target. This is backwards, according to the documentation according to the documentation it should be depends="build,update", but it works for me.

You'll notice that I've added an <exec> task to get the latest version from source control. This gets the latest version for the basedir and all child folders. I also updated my other default.build files for the other projects to do this step should I wish to only build a project.

So, I check commit these to Subversion and it fixes my problem right? Wrong! Because the existing default.build files in the d:\build\VirtualCellar folder don't have the new <target>s so the update never happens, I need to manually type the "svn update" command in the d:\build\VirtualCellar folder to bring down the latest version. In addition I also need to update the d:\program files\CruiseControl.Net\Server\ccnet.config file to build the new "buildLatest" target. Here's the updated ccnet.config file.

<cruisecontrol>
  <project name="VirtualCellar">
    <webURL>http://localhost/ccnet</webURL>
    <schedule type="schedule" sleepSeconds="300"/>
    <sourcecontrol type="svn">
      <executable>D:\program files\subversion\bin\svn.exe</executable>
      <trunkUrl>file:///D:/Svn/VirtualCellar/trunk</trunkUrl>
    </sourcecontrol>
    <build type="nant">
      <executable>D:\Program Files\nant-0.84\bin\nant.exe</executable>
      <baseDirectory>D:\Build\VirtualCellar</baseDirectory>
      <buildFile>default.build</buildFile>
      <buildargs></buildargs>
      <targetList>
        <target>buildLatest</target>
      </targetList>
      <buildTimeoutSeconds>300</buildTimeoutSeconds>
    </build>
    <publishers>
      <xmllogger>
        <logDir>..\web\log</logDir>
      </xmllogger>
    </publishers>
  </project>
</cruisecontrol>

In addition to the change in the <target> node, you'll see that I've added a <publishers> node that contains an entry for a log directory. This is where the resulting build log will get created. I made a d:\program files\cruisecontrol.net\web\log folder and pointed the logdir there.

Setting up the Web

I went and setup a Virtual Directory in IIS to point to the d:\program files\cruisecontrol.net\web folder and named it CCNET, so now when I go to http://localhost/ccnet, I get a screen like this

You can see here that it took me a few tries to get the build to successfully get the latest version from source control. This entry shows that the last build was successful, and it's been an hour since it's done another build. Remember it checks to see if there are any changes, and builds if there are any.

You may also notice the "Test Details" and "FxCop" links. CruiseControl.Net will automate these for you as well. That will be my next task for CC.Net. ThoughtWorks gives a nice overview picture on how CruiseControl.Net works.

Unit Tests for First User Story Complete

I've completed my first set of Test Cases for my first User Story. All of them pass!

I've ended up with the following two classes (Cellar & Wine). I'm satisfied with the current implementation for the first user story, but I can already see problems with this implementation. I need to switch focus to the Wine class and devote some modeling time to my project. In particular how Wine objects come into being. I think there's a WineCatalog or somesuch class in my future that will hold all of the known wines. So that's what I'll be working on today and hopefully publish my intial model tomorrow!.

with 0 Comments

Cruisin' With CruiseControl.Net

As I said in my last entry, I wanted to begin setting up my environment for the Virtual Cellar using Continuous Integration. A free software package that does that for me is CruiseControl.Net

I downloaded CruiseControl.Net version 0.6.1 and unzipped it to my D:\Program Files\CruiseControl.Net folder.

Configuring Cruise Control

As you recall I'm using Subversion for my source code provider and NAnt for my build tool. At a minimum this is what I need to get cruise control working.

Editing the ccnet.config file

The default installation of cruise control comes with a D:\Program Files\CruiseControl.Net\server\ccnet.example.config configuration file. I removed a lot of the information from this file, and tailored it to work with my installation of Subversion.

<cruisecontrol>
  <project name="VirtualCellar">
    <webURL>http://localhost/ccnet</webURL>
    <schedule type="schedule" sleepSeconds="60"/>
    <sourcecontrol type="svn">
      <executable>D:\program files\subversion\bin\svn.exe</executable>
      <trunkUrl>file:///D:/Svn/VirtualCellar/trunk</trunkUrl>
    </sourcecontrol>
    <build type="nant">
      <executable>D:\Program Files\nant-0.84\bin\nant.exe</executable>
      <baseDirectory>D:\Build\VirtualCellar</baseDirectory>
      <buildFile>default.build</buildFile>
      <targetList>
        <target>build</target>
      </targetList>
      <buildTimeoutSeconds>300</buildTimeoutSeconds>
    </build>
  </project>
</cruisecontrol>

As you can see, I've named my project "VirtualCellar". We'll skip the <webUrl> entry for now, as I haven't yet setup the website. <schedule> node tells cc.net to check for changes in the <sourcecontrol> every 60 seconds. (This is probably too short for me, but I'll leave it set that way for now).

I've also setup the <sourcecontrol> node to use Subversion and pointed it to my installation of the subversion program files. In addition, I need to point to the trunk (or root) of my Virtual Cellar project in the Subversion repository. CC.Net supports many different types of source control programs.

CC.Net and NAnt

I next need to tell CC.Net how I plan to build my application. As you may recall I've installed and configured  my Virtual Cellar project to be built with Nant. I do this by pointing to the NAnt executable (I moved it since my last installation from d:\nant-0.84 to d:\program files\nant-0.84, I also need to check into using environment variables rather than hard coded paths).

I need to tell CC.Net where to build the continuous integration version of the Virtual Cellar project. When I setup Subversion, I chose D:\VirtualCellar for "my working copy".  I don't want CC.NET to use that folder because that's *my* project and I may have files that I'm working on that aren't checked in to Subversion. So, I have to setup a working folder for Subversion. Normally CC.Net would run on a dedicated Build Server, but for now I'm running it on my dev machine.

So, in looking back at my Subversion post, I need to create a build folder and then checkout the latest version of the VirtualCellar project to that folder. The following box shows the result. You can see all the work I've done so far, I have my documentation, two projects (Lorengo.VirtualCellar.Business and Tests) along with their associated .csproj and NAnt build files.

D:\>md build
D:\>cd build
D:\build>svn checkout file:///d:/svn/VirtualCellar/trunk VirtualCellar
A  VirtualCellar\VirtualCellar.sln
A  VirtualCellar\default.build
A  VirtualCellar\Doc
A  VirtualCellar\Doc\rup
A  VirtualCellar\Doc\rup\02Elaboration
A  VirtualCellar\Doc\rup\01Inception
A  VirtualCellar\Doc\rup\01Inception\VirtualCellar.BusinessCase.doc
A  VirtualCellar\Doc\rup\01Inception\VirtualCellar.Vision.doc
A  VirtualCellar\Lorengo.VirtualCellar.Business
A  VirtualCellar\Lorengo.VirtualCellar.Business\AssemblyInfo.cs
A  VirtualCellar\Lorengo.VirtualCellar.Business\Cellar.cs
A  VirtualCellar\Lorengo.VirtualCellar.Business\default.build
A  VirtualCellar\Lorengo.VirtualCellar.Business\Lorengo.VirtualCellar.Business.csproj
A  VirtualCellar\Lorengo.VirtualCellar.Business\Wine.cs
A  VirtualCellar\Lorengo.VirtualCellar.Business.Tests
A  VirtualCellar\Lorengo.VirtualCellar.Business.Tests\AssemblyInfo.cs
A  VirtualCellar\Lorengo.VirtualCellar.Business.Tests\default.build
A  VirtualCellar\Lorengo.VirtualCellar.Business.Tests\Lorengo.VirtualCellar.Business.Tests.csproj
A  VirtualCellar\Lorengo.VirtualCellar.Business.Tests\CellarFixture.cs
Checked out revision 9.

When all is said and done I now have another working copy of my Virtual Cellar project for CC.Net in the D:\Build\VirtualCellar folder. This is what I set as my <baseDirectory> and point to the default.build file as my <buildFile>. The <target> tells NAnt which target in the build file to build, for now I have 2 targets, "clean" and "build" (which is dependent on "clean"). I'll be adding more targets going forward but for now I'll use the "build" target.

And that's it! I'll save this file as ccnet.config

Running  CruiseControl.Net

All that is left to do is run the cruise control server, here's the output...

D:\Program Files\CruiseControl.Net\server>ccnet
[CruiseControl Server:Info]: CruiseManager: Listening on tcp://192.168.1.100:21234/CruiseManager.rem
[CruiseControl Server:Info]: Starting CruiseControl.NET Server
[CruiseControl Server:Info]: Reading configuration file "D:\CruiseControl.Net\server\ccnet.config"
[CruiseControl Server:Info]: Starting integrator for project: VirtualCellar
[VirtualCellar:Info]: Starting integration for project: VirtualCellar
[VirtualCellar:Info]: 25 modifications detected.
[VirtualCellar:Info]: Building
[VirtualCellar:Info]: Build complete: Success
[VirtualCellar:Info]: Integration complete: 9/27/2004 7:23:25 PM
[VirtualCellar:Info]: No modifications detected.
...(more of same deleted)...
[VirtualCellar:Info]: No modifications detected.
[VirtualCellar:Info]: 1 modification detected.
[VirtualCellar:Info]: Building
[VirtualCellar:Info]: Build complete: Success
[VirtualCellar:Info]: Integration complete: 9/27/2004 7:49:37 PM

The first time it runs it knows that it hasn't built anything so it detects all of the changes so far and runs the build successfully (Yeah!). I'll now go ahead and add a new test to the CellarFixture.cs class. Here's what it looks like in Windows Explorer with TortoiseSVN installed.

You can see that the CellarFixture.cs is flagged as up to date, here's what it looks like after I modify it with a new test, and then save the file.

It's flagged as being different or updated. It isn't until I right+click on the file and say "Commit" from the TortoiseSVN context menu that the file is committed to Subversion. (Of course I've compiled and tested it on my machine before I do this so I don't "break the build"). Once I commit my changes, Cruise control detects the change (every 60 seconds for now), and issues the build with another Success! As my project grows and takes more time to build, I'll probably want to change the schedule to every hour or so...

That's it! I've got a integration server that will now build when changes to the repository are detected. I can now continue with more development. Of course there are other things that I'll want to add to my continuous integration pipeline, like automagicall running NUnit (or MbUnit) tests, FxCop rules, and eventually creating an install package. Ahh! what the future holds.

Odds and Ends - MSBuild with NAnt

In my Refrigerators, Unit Testing and NAnt post Kirk Maple asked about using MSBuild with NAnt, one possible solution would be to do the following...

<target name="build">
  <sysinfo />
  <exec program="PathToMSBuild\MSBuild.exe"
        commandline="MyProject.csproj" />
</target>

Seeing as I didn't install the Team System Yet, I don't have MSBuild on my machine, so Your Mileage May Vary.

with 0 Comments

Subverted! Setting Up Subversion

I decided to install two source code control providers so that I can begin putting my project under source code control. My initial choices for evaluation were going to be CVS, Subversion and Source Safe, after looking at Subversion, I see no reason to try and install CVS since it's more or less compatible with CVS with some added functionality. Here is an interesting comparison of source control providers. Granted it doesn't include comparisons with SourceGear's products or PVCS.

Eric Sink has written on online book on Source Control: How To

Installing Subversion

Subversion is billed as a better version of CVS. I chose to download release 1.1.0rc3 because according to the release notes it allows the repository to be file system based as opposed to using BerkelyDB. The release I'm downloading is for Win32 and is packaged as a setup program, and basically it runs the install and that's it.

I'm also installing TortoiseSVN which presents a nice GUI interface (similar to TortoiseCVS for CVS) into Subversion. I'm installing version 1.1.0rc2, here are the release notes.

Configuring Subversion

The Subversion Book is an excellent free resource for determining how to use Subversion. In addition Mike Mason advocates setting up a Single Repository over Multiple Repositories in subversion and also lists some suggestions for Effective Source Control

Creating A Repository

I'll use the command line tool to create a repository. I'll want to create the repository using the file system rather using the BerkeleyDB structure. This will allow me to access the file system remotely.

D:\>svnadmin create svn -fs-type fsfs

Adding to the Repository

After creating a repository in the d:\svn folder, I'm going to create a tmpdir and establish a folder layout for my new project. I could use the svn mkdir command if I wanted to, but since I'll be adding a few directories I'll use the svn import command.

D:\>mkdir tmpdir
D:\>cd tmpdir
D:\tmpdir>mkdir VirtualCellar\trunk
D:\tmpdir>mkdir VirtualCellar\branches
D:\tmpdir>mkdir VirtualCellar\releases
D:\tmpdir>svn import -m "Initial Layout of VirtualCellar Project" file:///d:/svn

Adding         VirtualCellar
Adding         VirtualCellar\releases
Adding         VirtualCellar\trunk
Adding         VirtualCellar\branches

Committed revision 1.
 

I'll now go ahead and delete the tmpdir and list the files in the repository using the svn list command

D:\tmpdir>cd ..
D:\>rmdir /s tmpdir
D:\>svn list -v file:///d:/svn
      1 mlorengo            Sep 21 12:17 VirtualCellar/

Checking out the project

Now that I have a project in svn, I'll go ahead and checkout the trunk to perform some work like adding my intial RUP documentation to the repository, but before I do that I'll use the svn mkdir command to make a Doc\rup folder under the trunk where my Inception and Elaboration documents will reside.

D:\>svn checkout file:///d:/svn/VirtualCellar/trunk VirtualCellar
Checked out revision 1.
D:\>cd VirtualCellar
D:\VirtualCellar>svn mkdir Doc
A	Doc

D:\VirtualCellar>cd doc
D:\VirtualCellar\Doc>svn mkdir rup
A	rup

D:\VirtualCellar\Doc>cd rup
D:\VirtualCellar\Doc\rup>mkdir 01Inception
A	01Inception

D:\VirtualCellar\Doc\rup>mkdir 02Elaboration
A	01Elaboration

D:\VirtualCellar\Doc\rup>cd 01Inception
D:\VirtualCellar\Doc\rup\01Inception>

Now that I have my directory structure built, I'll go ahead and commit the changes queued thus far

D:\VirtualCellar\Doc\rup\01Inception>svn commit -m "Added rup documentation folders"

Now I can copy my BusinessCase.Doc and my Vision.Doc documents to the 01Inception folder and add them to the repository

D:\VirtualCellar\Doc\rup\01Inception>svn add Vision.Doc
D:\VirtualCellar\Doc\rup\01Inception>svn add BusinessCase.Doc
D:\VirtualCellar\Doc\rup\01Inception>svn commit -m "Added Inception Documents to repository"

What's Left To Do

Now that I have Subversion setup, there are still a few more things left to do. I'll need to work out security, so I know who's checking in what, and I'll need to figure out the svnserve -d option so that I can pull information from the repository remotely.

I know I promised some Use Cases and User Stories today, but it appears that those tasks have been subverted (ouch!). I'll work on them the rest of the day and maybe get them posted later on this evening.

with 2 Comments