Monday, May 11, 2009

CCNet : how to upgrade to a new version

I've been using CCNet for some years, and here is how I upgrade it :
  • stop all projects, or certainly the CI ones
  • stop ccnet service/console
  • take backup of the server and dashboard folders (zip them) just to be on the safe side
  • copy over the new binaries (including templates, xsl files, ...)
  • start ccnet service/console
  • start the projects again
I never do an install over an existing one, because in the past you would loose your ccnet.config file, which is a pain, and sometimes you lost a .state file, which is VERY painfull. We're in the process of making upgrades less painfull though.

Now if you have only a couple of CCNet projects, you can click stop on each of them, but if you got dozens, this will take some time. And since I'm into automation, I do not like to do repeatative jobs, these are sure to give errors one time. Unfortunately there is no built in mechanism to stop all projects, or a group of projects, but all the functionality exists. I took a look at CCTray, and after some time I figured it out. I'll save you the trouble, just copy the code below. I know, not the most clear code, but it is on the to-do list for a major refactor.
The code is a VB.Net console program, but perfectly usable :-)
Pass start or stop as argument, to start/stop projects not in de Deployment category.
Imports ThoughtWorks.CruiseControl
Imports ThoughtWorks.CruiseControl.Remote

Module Module1

Private BuildServerManager As CCTrayLib.Monitoring.ICruiseServerManager
Private Const BuildServerUrl As String = "tcp://buildserver:21234"

Sub Main()
Dim args As String()

Dim StopProjects As Boolean

args = Environment.GetCommandLineArgs()
If args.Count <> 2 Then
Console.WriteLine("{0} State ", args(0))
Console.WriteLine(" example : {0} stop to stop all CI projects", args(0))
Console.WriteLine(" example : {0} start to start all CI projects", args(0))
Throw New Exception()
End If

StopProjects = args(1).ToLower = "stop"

BuildServerManager = CreateBuildServerManager()

Dim CruiseSnapShot As Remote.CruiseServerSnapshot = BuildServerManager.GetCruiseServerSnapshot

Dim CruiseManager As Remote.ICruiseManager

Dim z As New Remote.RemoteCruiseManagerFactory
CruiseManager = z.GetCruiseManager(BuildServerUrl)

For Each project As Remote.ProjectStatus In CruiseSnapShot.ProjectStatuses

If Not project.Category.StartsWith("Deployment") Then

If project.Activity = Remote.ProjectActivity.Sleeping AndAlso StopProjects Then
Console.WriteLine("Stopping {0} ...", project.Name)
End If

If project.Status = ProjectIntegratorState.Stopped AndAlso Not StopProjects Then
Console.WriteLine("Starting {0} ...", project.Name)
End If

End If

Catch ex As Exception

End Try


End Sub

Private Function CreateBuildServerManager() As CCTrayLib.Monitoring.ICruiseServerManager
Dim RemoteCruiseManagerFactory As Remote.RemoteCruiseManagerFactory = New Remote.RemoteCruiseManagerFactory
Dim Factory As CCTrayLib.Monitoring.CruiseServerManagerFactory = New CCTrayLib.Monitoring.CruiseServerManagerFactory(RemoteCruiseManagerFactory)
Dim Manager As CCTrayLib.Monitoring.ICruiseServerManager = Factory.Create(CreateBuildServer())

Return Manager

End Function

Private Function CreateProjectManager(ByVal projectName As String) As CCTrayLib.Monitoring.ICruiseProjectManager
Dim server = CreateBuildServer()
Dim remoteCruiseManagerFactory As ICruiseManagerFactory = New RemoteCruiseManagerFactory()
Dim factory As CCTrayLib.Monitoring.CruiseProjectManagerFactory = New CCTrayLib.Monitoring.CruiseProjectManagerFactory(remoteCruiseManagerFactory)
Dim projectConfig As CCTrayLib.Configuration.CCTrayProject = New CCTrayLib.Configuration.CCTrayProject(server, projectName)

Dim serverList As Collections.Generic.Dictionary(Of CCTrayLib.Configuration.BuildServer, CCTrayLib.Monitoring.ICruiseServerManager) = New Dictionary(Of CCTrayLib.Configuration.BuildServer, CCTrayLib.Monitoring.ICruiseServerManager)

serverList.Add(server, CreateBuildServerManager)

Dim manager As CCTrayLib.Monitoring.ICruiseProjectManager = factory.Create(projectConfig, serverList)

Return manager

End Function

Private Function CreateBuildServer() As CCTrayLib.Configuration.BuildServer
Dim serverName = BuildServerUrl.ToLower

If Not serverName.StartsWith("tcp://") Then
Throw New Exception("set up the url as remoting, url used : " + BuildServerUrl)
End If
serverName = serverName.Substring(6)

Return CCTrayLib.Configuration.BuildServer.BuildFromRemotingDisplayName(serverName)

End Function

End Module


  1. if you have perforce as depossit then you will need to (re)compile the new version to include the PerforceLabeller.cs

  2. to avoid loosing config you can put it into source control, and then just add path into ccservice.config pointing to it:


  3. Config modification:

    <add key="ccnet.config" value="config\ccnet.config" />