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:
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.
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.
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.
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With