.net – Build order in CruiseControl.NET with project dependencies

continuous integrationcruisecontrol.netnet

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.

Best Answer

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.

Related Topic