Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Build order in CruiseControl.NET with project dependencies

In our .NET software development shop, we have CruiseControl.NET set up to build 28 projects, some of which are interdependent. Each project approximately represents a Visual Studio projects or Flex library paired with unit tests. What I'm annoyed at is that I haven't found a good way to ensure that projects build in an order representing the dependencies.

Here's what I am doing:

  1. Everything is in the same build queue. I did this so that builds are done sequentially and so I can avoid needing multiple working directories.
  2. I set queue priorities on the projects, which I thought would influence their build order. But after reading the documentation more carefully, I found that it just controls prioritization when there are multiple build requests in a queue.
  3. In addition to using interval triggers to kick off a build, I use project triggers so that when dependencies successfully build, their dependents also build.

In a way, this setup works. The main problem is if somebody commits changes to the code in both project A and project B, where project B is dependent on project A. Sometimes, project B will build before project A. Because project A hasn't been build yet, this can sometimes cause project B to break. This is temporary, since the interval trigger causes project A to build later on, and its successful build triggers project B to rebuild and get fixed. What I want to avoid is project B building before project A so that intermediate breakage cannot happen.

Which practices do you use to properly manage interdependencies on a CruiseControl.NET server? At this point, I'm not willing to change to a non-free continuous integration package like TeamCity.

like image 261
Jacob Avatar asked Jun 12 '09 19:06

Jacob


3 Answers

Don't put the dependency in the CC.NET project settings. You need to control the project build order via the NAnt script. You don't have to build on a solution level, you can build on an individual project level.

<target name="Project1" depends="Projects2" description="Builds project 1">
     <msbuild>
        <executable>C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\MSBuild.exe</executable>
        <workingDirectory>C:\dev\ccnet</workingDirectory>
        <projectFile>CCNet.sln</projectFile>
        <buildArgs>/noconsolelogger /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>
</target>

<target name="Project2" depends="Projects3" description="Builds project 2">
     <msbuild>
        <executable>C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\MSBuild.exe</executable>
        <workingDirectory>C:\dev\ccnet</workingDirectory>
        <projectFile>CCNet.sln</projectFile>
        <buildArgs>/noconsolelogger /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>
</target>

<target name="Project3" description="Builds Project 3">
     <msbuild>
            <executable>C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\MSBuild.exe</executable>
            <workingDirectory>C:\dev\ccnet</workingDirectory>
            <projectFile>CCNet.sln</projectFile>
            <buildArgs>/noconsolelogger /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>
</target>

You can run your unit tests on an individual project level, so you shouldn't need to make duplicate runs over multiple projects.

like image 86
The Matt Avatar answered Nov 15 '22 08:11

The Matt


I suggest that you don't cross the concept of a CruiseControl project with a visual studio project! I generally set up a CC project that encompasses a body of work. For me this means that the CC project will run a NAnt script. The NAnt script has very fine grained control over what I do and when. This means that I can build my solution (which knows which project to build first!), run my unit tests, reset a database, deploy some code, send out some emails, do some code analysis (NDepend and NCover are great!), etc. This means that I have one project show up in CCTray and this keeps things more true to what they actually are. I then can create a new project in CC to control when I push from DEV to STAGING and from STAGING to PROD so that we can "push button" this task. But this yields only 3 projects in cruise control and is considerably more user friendly.

like image 45
Andrew Siemer Avatar answered Nov 15 '22 09:11

Andrew Siemer


Although you have already accepted an answer, I would suggest something else: you shouldn't have direct dependencies between two projects. By "direct" I mean that every time binaries in the project A change, this shouldn't mean you automatically use them to build the project B.

The process of updating these references should be controlled (by you), otherwise you will inevitably end up with a lot of broken builds for the project B.

I tend to keep all external binaries under lib directory (and subdirectories) under source control and update them only when I decide to do so. And by "external" I mean both 3rd party libraries and those from other projects in my company (example: http://code.google.com/p/projectpilot/source/browse/#svn/trunk/lib)

like image 30
Igor Brejc Avatar answered Nov 15 '22 08:11

Igor Brejc