Introduction
Recently I’ve been playing around with some client applications for CruiseControl.NET (more on this in a later post). As I was coding, I realised it is not that easy to work with entities for CruiseControl.NET. Yes, there is a new communications library that simplifies the communications, but it still requires a knowledge of which method does what.
It would be nice if there were some high level entities that simplify this process and hides all the method calls. Additionally, it would be nice if these entities stayed up-to-date with the actual server. This would be useful in a number of places – including both CCTray and the dashboard.
So I sat down and put together a high level API. This is built on top of the communications library – so under the hood it just uses the messaging. But it does abstract away these details – instead of calling the communications API and passing in the correct parameters, you just initialise the Monitor API and then use the entities returned.
Before I continue, I should mention, this is my first cut of it. I have been trialling it out and it “kind-of” works, but it is still very rough around the edges. Of course, this will only be relevant to you if you are interested in developing applications to communicate with the CruiseControl.NET server.
The API
The API exposes four entities (currently):
These classes expose most of the information about the current status of the server. When I say current, I mean as of the last snapshot taken of the server. They don’t include historical details (yet).
The Server class provides a high-level overview of the server. Currently, this only lists the projects and the servers that are available, but it does provide notifications of when projects or queues are added or removed from the server. Additionally, this is the root level class for the API. To interact with the API you will need to create an instance of this class – more on this later.
The Project class provides details on the current status of a project. This is all taken from the snapshot method, so it doesn’t include historical details. It does contain all the details that are currently available in CCTray or the projects grid of the dashboard (e.g. current status, current activity, next and previous build times, etc.)
The BuildQueue class does the same for an integration queue, although there are less details available for a queue. It does expose an array of BuildQueueRequest instances, which contains details on each current or pending request for the queue.
These four classes are all tied together, which eliminates some of the problems we have in CCTray. For example, in the Module API, it is easy to find out which server a project belong to, as there is a direct relationship between the two (Project has a property called Server, which points to the Server instance).
Additionally, there are a number of helper methods (with more to come). If you need to build a project, there is a method called ForceBuild() which does exactly that. under the hood, these methods call the communications API to pass the requests onto the server, but someone using the Monitor API does not need to know this.
Events and Monitoring
One of the key parts of the Monitor API is change notifications. The API can be configured so it automatically monitors the server (hence the reason for its name). When the server changes (e.g. adding/removing a project/queue, a project starting building, etc.) an event is triggered.
Most of the classes implement INotifyPropertyChanged, so a PropertyChanged event will be fired when a property on the server changes. There is also a new set of events for when a project, build queue or build queue request is added or removed.
This makes it easy for a client to detect any changes – just initialise the Server instance with a polling watcher and the events will be fired automatically. This makes it incredibly easy to set up applications that “watch” a server and do things when the server changes.
Some Examples
Rather than go into the details of how the API works, I thought I’d finish off with some examples so people can see how it works.
First of all, to initialise the API, a new server instance needs to be created. Since this relies on the communications API underneath, it needs an instance of CruiseServerClientBase. The following shows how to initialise the client and then the server:
1: var client = factory.GenerateClient(clientAddress);2: var server = new Server(client);3: server.Refresh()
The first line creates the new client instance, the second then creates the server instance. The third line is not strictly necessary, but it will force a refresh of the data from the server (otherwise it will wait until the server is polled).
Once the server is initialised, it is easy to work with both projects and queues. There are both Projects and BuildQueues properties to list all of the projects and queues. Alternately, if you know which project or queue is needed, there are FindProject() and FindBuildQueue() methods to search by name. For example, to force a build on a project you could use the following code:
1: var project = server.FindProject("CruiseControl.NET");2: project.ForceBuild();
Finally, here is an example of how to register an event for watching a status change:
1: var project = server.FindProject("CruiseControl.NET");2: project.PropertyChanged += (o, e) => {3: if (e.PropertyName == "Status") {4: // Do something for a status change5: }6: };
And for a new build request on a queue:
1: var queue = server.FindBuildQueue("CruiseControl.NET");2: queue.BuildQueueRequestAdded += (o, e) => {3: // Do something when a new build request is queued4: };
Of course, these are just some of the things that can be done, plus I should mention that there are still a lot of things that cannot be done (at least not directly).
Where To Next?
Over time I’m planning on expanding the API to cover a lot more tasks. Initially I plan on including all the information and tasks that are available in CCTray 1.5.0. Most of this has already been done, but I still need to include status breakdowns and package lists.
Once this is feature complete, I’ll start looking at how to include historical data – previous build results, history and statistics, etc. This will cover most of the information that is available in the dashboard.
At the same time I am working on a little side project that is using the new Monitor API. This has mainly been a test bed for concept, which I’m looking at releasing as a separate project (more on this later on).
Once the API is complete and useful, I might (and I’ll stress the “might” part) convert both CCTray and the dashboard to use it. This would certainly simplify a lot of the “horrible” code in these two clients. The bad news is it getting harder to work with these two clients, and trying to unwind all the complexities around communications is challenging (hence the reason for some of the existing bugs!)
In Conclusion
Hopefully, this gives an idea of what can be done with the new Monitor API, and also some of its current limitations. Over time I’m planning on expanding it to provide any necessary information from CruiseControl.NET, by which time it should be easy to build clients for the system.
And finally, I have a surprise coming, although it’s not completely new news.
Stay tuned…
RSS - Posts