Automated Coder

Exploring the Code of CruiseControl.Net

Documentation: Server Configuration Completed

Posted by Craig Sutherland on 17 December, 2009

I have now finished migrating the configuration documentation for the server into the code base. This means all the values for the server configuration are documented (although sometimes not well). This also included adding any missing documentation and ensuring everything is in a consistent format.

So take a look and leave a comment in the documentation if you notice anything that should be corrected.

Note: Do NOT leave comments about bugs or issues in the documentation! We do not read these very often. If you need to log a bug, please use either the mailing lists (see http://confluence.public.thoughtworks.org/display/CCNET/Mailing+Lists) or JIRA (see http://confluence.public.thoughtworks.org/display/CCNET/Issues).

And yes, I know people will ignore the note, deleting comments gives me something nice and easy to do :-)

Posted in CruiseControl.Net | Tagged: | 1 Comment »

Parlez-vous Français

Posted by Craig Sutherland on 16 December, 2009

A Long Time Ago…

Back in the 1.4 days, when we were still investigating what to put into 1.5, I looked into adding multi-lingual support to CruiseControl.NET. Basically I had hoped to make CruiseControl.NET available to more people, especially those who did not speak English (or for whom English was not their first language).

As nice as the idea was, there was one major snag – no translators :-( So after a while the idea died a death. Unfortunately, my linguist ability is extremely limited (I’m learning Chinese, but it’s a painful and slow process!) So when we started preparing for the 1.5 release, the multi-lingual changes were dropped.

Recently, one of our users asked how to switch languages in the dashboard. When we told him it couldn’t be done, he came back with an offer of translating into French for us! So I have dusted off some of the old archived code and re-added multi-languages to CruiseControl.NET.

Keeping It Simple

Now the original version of the multi-lingual changes started with the Remote project and worked their way up through Core, Server and then onto the Dashboard (CCTray was bypassed). This meant, in theory, an administrator could completely switch their CC.NET install into a different language.

While this was a grand vision, it had a few detractors. For one, should exceptions be translated? (I said yes, others said no.) What about documentation? (Especially considering our documentation needs some TLC anyway.) What about support? Testing? Etc.

So for this second attempt I have pared it right back. The only thing that is translated is the dashboard – everything to do with the actual CI server is untouched. This, hopefully, bypasses most of the above concerns, while still allowing non-English speakers to use the system.

Additionally, I changed the code slightly. Originally the language was hard-coded – everyone had to use the selected language. The new version uses the language detection in ASP.NET and selects the user’s primary language (as specified by their browser).

Now for the bad news – currently there is only one translation, French, and it is still a work in progress. So, if you speak French, here is what the dashboard looks like currently:

image

And just to show that it is different, if I change my language back to English:

image

Acknowledgements

As I mentioned earlier my linguist ability is virtually nil. Louis-Philippe Carignan is the kind volunteer who provided the French translation. Many thanks Louis-Philippe, I hope this helps you :-)

Posted in CruiseControl.Net | Tagged: | 4 Comments »

Dynamic Parameters and Configuration: Inner Workings

Posted by Craig Sutherland on 15 December, 2009

What’s So Hard About Them?

It appears that one of the more popular improvements for the 1.5 release is dynamic parameters (and their associated elements dynamic values). A dynamic parameter allows an administrator to define a project definition with some “placeholders”. When the project runs, it populates these “placeholders” from either user-specified values or some defaults.

Now, the concept is very, very simple – just replace some item with a value. Unfortunately because of the way configuration has been implemented in CruiseControl.NET, this is not that simple a task :-( So let’s take a look at how configuration works in CruiseControl.NET and how it has been “hacked” to allow for dynamic parameters.

From Text to Data

At the moment, all the configuration for CruiseControl.NET is loaded from a XML file (basically a plain text file). This gets converted from XML (which is not very useful to the system) to POCOs (Plain Old Class Objects). A developer new to CruiseControl.NET would think that this involves a bit of magic (I certainly did!)

The way this conversion works is via a third-part library called NetReflector. This uses attributes on the classes to convert the XML into POCOs. For example, here is a piece of the executable task:

[ReflectorType("exec")]
public class ExecutableTask
    : BaseExecutableTask
{
    [ReflectorProperty("executable", Required = true)]
    public string Executable = string.Empty; 

    [ReflectorProperty("baseDirectory", Required = false)]
    public string ConfiguredBaseDirectory = string.Empty; 

    [ReflectorProperty("buildArgs", Required = false)]
    public string BuildArgs = string.Empty; 

    [ReflectorArray("environment", Required = false)]
    public EnvironmentVariable[] EnvironmentVariables = new EnvironmentVariable[0];

    [ReflectorProperty("buildTimeoutSeconds", Required = false)]
    public int BuildTimeoutSeconds = DEFAULT_BUILD_TIMEOUT;

    // Other code omitted
}

The ReflectorType attribute at the start of the class defines <exec> as an item that can appear in the configuration. The ReflectorProperty attributes then define the allowed values on <exec>. So far, so good.

The first three properties defined are all strings – so these get converted into strings within the POCO. The fourth property is an array of EnvironmentVariables – so what happens here? This is where NetReflector does its stuff and automatically generates POCOs from the XML configuration. The same happens with the last property, which is an int, NetReflectors handles the conversion automatically.

This process is all done at start-up. CruiseControl.NET starts up, loads the configuration, runs it through NetReflector and the resulting POCOs are then fixed until the configuration is reload. In theory the values from the configuration are supposed to be read-only after the configuration has been loaded, but it is possible that the classes can change their configuration values :-(

What’s The Big Deal?

At this point, you may be wondering what the big deal is?

When people want dynamic parameters, they also want a nice easy way to use them. For example, if the project had parameters for baseDirectory and time-out, people want to use the following type of configuration:

<nant>
  <baseDirectory>$[baseDirectory]</baseDirectory>
  <buildTimeoutSeconds>$[timeout]</buildTimeoutSeconds>
</nant>

Now baseDirectory is no problem, because the underlying data type is a string. But how do we handle timeout? The underlying data type is an int – so NetReflector tries to convert this and fails with an exception! Nasty :-(

And unfortunately, due to the way NetReflector works, it is not an easy change to handle this.

Evolution of Dynamic Values

When I first started on this feature I added dynamicValues as another configuration element. So the above example would be written as:

<nant>
  <baseDirectory>C:\Somewhere</baseDirectory>
  <buildTimeoutSeconds>600</buildTimeoutSeconds>
  <dynamicValues>
    <directValue>
      <parameter>baseDirectory</parameter>
      <property>baseDirectory</property>
      <default>C:\Somewhere</default>
    </directValue>
    <directValue>
      <parameter>timeout</parameter>
      <property>buildTimeoutSeconds</property>
      <default>600</default>
    </directValue>
  </dynamicValues>
</nant>

Now this worked (more on this below), but as you can see the parameters now take up more space then the actual task definition! When the feature was first released this is the first thing they complained about.

So, I went back to the drawing board.

Now the application liked the dynamicValues element because it allowed it to change the settings when the project was run. Even though the underlying value is changed, because the dynamicValues element is static, the application can reset them because it always knows what to set. People didn’t like this because it was extra work, plus it was harder to figure out exactly what needed to be where (plus if you misspelt the property name, things didn’t work!)

In contrast people liked the short-hand version – it was similar to other programs (e.g. NAnt, MSBuild, etc.), it reduced the possibility of errors and most importantly – it was less typing. The application hated it because of NetReflector (see above) and even for string values it caused problems (the value was being overwritten.)

Thus we had two solutions – one that people liked but was technically impossible and the other that worked but was disliked. So the next step in the evolution of this feature was to add a converter from one to the other.

Configuration Pre-processing

CruiseControl.NET already has a pre-processor, but after looking at it, I went with a different approach (it was too complex to try and add it to the existing processor). The new pre-processor is specific to dynamic values and it involved hacking NetReflector a little. The change was very simple – NetReflector will check to see if a class has a pre-processor method on it, if it does it passes the XML for that class into that method to be converted.

The CruiseControl.NET side involved converting the shorthand parameters into the full XML definition. So the user would enter the first (short) version, the pre-processer would convert it and the application would see the second (long, ugly) version. This provides a win-win situation for both the application and the users :-)

Now, I could go into the technical details on how it does this, but if you really want to see how, take a look at the code. All I’ll say for now is it scans all the elements and attributes for any short-hand parameters and then generates a matching parameter for it in the configuration. It is a little nasty in the conversion step, because it needs to handle sub-properties and arrays, but it appears to be working.

And Finally, How are They Used?

The pre-processing is all to set up the dynamicValues element. This then gets converted into POCOs so the CruiseControl.NET can use them. The actual usage is at run-time. When a project runs a task (or a labeller or source control block) that has parameters it will pass the parameters into that task (or other item). In order for this to work, the item needs to implement IParamatisedItem, which is the interface that says “hey, I can use parameters”.

To help with using parameters there is a static utility class called DynamicValueUtility. This uses reflection to find the property and set its value. The tricky part was matching the configuration property name to the actual property name (since one is in the code and the other is set via an attribute), but it is all working, including handling arrays. The actual classes then call this utility class to perform the actual work.

To make things even simpler, there are a few base classes (TaskBase, LabellerBase and SourceControlBase) that implement this functionality by default. All a class needs to do is derive from one of these classes and it automatically get dynamic parameters functionality.

That’s All Folks

This has been a quick look at dynamic parameters and how they came to pass in CruiseControl.NET. Hopefully in a future version we’ll make them work even better, but considering the current limitations, this provides a working implementation :-)

Posted in CruiseControl.Net, Inner Workings | Tagged: | Leave a Comment »

XSD Version Information

Posted by Craig Sutherland on 14 December, 2009

The Problem

In my last post I talked about adding an XSD schema to CruiseControl.NET. This allows us to use tools like the Intellisense in Visual Studio and XSD validators. However one of the issues around generating XSDs for something like CruiseControl.NET is knowing which schema to use. As new versions of CruiseControl.NET are released, new features are added and additional configuration elements are added.

CruiseControl.NET already has this issue when it reads configuration files, but it takes a very approach – it assumes the configuration is for the current version! This means if it comes across configuration elements it doesn’t like, it throws the dummy and stops!! Now, most of the time we try to ensure any configuration changes are backwards compatible, but every now and then a breaking change works its way through to a release.

A Solution

It turns out there is exactly a fairly simple answer to these issues, and it is provided natively by XML – the answer is XML namespaces. An XML namespace is simply an xmlns definition in the XML file, which points through to a URI. The great news is this URI does not even have to exist (which at times makes things confusing!)

To use an XML namespace is as simple as the following example:

image 

This tells any XSD processors that the schema to use is identified by http://thoughtworks.org/ccnet/1/5. If you try to follow this URI you’ll get a 404, so I wouldn’t recommend it ;-)

This URI contains three important pieces of information:

  1. The organisation. For CruiseControl.NET I choose thoughtworks.org it was originally developed by them, plus they still provide the servers for the public site.
  2. The application – ccnet. This allows thoughtworks to have multiple different products without conflicts!
  3. The version – 1/5, which translates to 1.5.

The URI does not require these items, but it is a nice simple URI that provides all the information that I think we need.

Some Benefits

Now, onto the benefits. If you try to load my example above into any version of CruiseControl.NET, it will still work. CruiseControl.NET does not look at namespaces, it goes by the local names of elements and attributes, so this change is still backwards compatible. Since the namespace is not required, you can safely omit it and CruiseControl.NET will still work.

But, if you do add it, you can now use Intellisense in Visual Studio. You can also run your configuration through an XSD validator together with the schema to see if your configuration is valid (you can also use CCValidator, but we’re all about choices!)

Next, CruiseControl.NET has been modified to detect this namespace. It will look at the namespace and compare it to the application version. If there is a mismatch it will now tell you nicely :-)

Additionally, when we move to the next version of CruiseControl.NET (2.0?) we can look at doing automatic configuration conversion. In a nutshell, this is automatically upgrading the configuration so it works under the new version (where possible). This can be a one-time tool (similar to my migration wizard we tried out for a while) or be performed automatically when CruiseControl.NET loads an older configuration (although we would not persist the changes to disk).

Of course, this version updating won’t come into effect until we move to a new version, but it is a simple change that will help make CruiseControl.NET more future proof.

So, this is where I’m planning on taking the configuration for the moment, together with what I see as the benefits.

Posted in CruiseControl.Net | Tagged: | Leave a Comment »

CruiseControl.NET XSD – Second Attempt

Posted by Craig Sutherland on 12 December, 2009

A long time ago I tried to write an XSD for CruiseControl.NET. This used an old-fashion technique: copy-and-paste. I literally went through the entire documentation and copied and pasted all the configuration elements.

Now this schema had a large number of errors in it for the following reasons:

  • Copy-and-paste is only as good as the copy-paster doing the work
  • The documentation was missing a number of elements or was invalid
  • I didn’t fully understand how NetReflector worked
  • I didn’t fully understand how XSD worked
  • No documentation was copied

At the time it worked for me, so I was reasonably happy, but it was something that always stuck around in the back of my mind.

Now, a number of things have improved since my first attempt. I’m now the “owner” of NetReflector and I’ve spent some (serious) time understanding how it works. I’ve also done a lot more work with XSDs and figured out a number of new things (well old to those who understand XSDs). And finally, I’m in the process of going through and updating the documentation!

Anyway, part of doing the documentation involves generating examples where these are missing. Normally my process was to write the configuration by hand, and then run it through the validator. To find out what I wanted, I would look in the code and then build a minimal example. For the full example I would normally copy the “processed” element from the validator.

Now this guaranteed that I had working examples, but it involved a lot of to’ing and fro’ing, especially for the larger examples. That’s when I remember XSDs and intellisense in Visual Studio.

So, I have modified the documentation generator to also generate XSDs for the elements. That’s the good news, now for the issues. First and foremost, it is impossible to completely generate the XSD from the code base. I know, I tried, really, really hard – and still I couldn’t get it working – at least not without some serious changes to how NetReflector works (there are just too many areas where it was impossible to find out what was happening by code!)

So the documentation generator generates a 80% solution. It generates one XSD per configuration element and I then go through and complete the remaining 20%. Once the element has been completed I merge it into the main XSD – which is currently around 200Kb (it’s big and getting bigger!)

The second issue is how NetReflector works. If the data type is a primitive type (e.g. int, double, boolean, etc.) or a string, NetReflector does not care whether it is an element or an attribute. So to be 100% correct the XSD would have to handle this scenario. But, if both an attribute and an element of the same type is added (or multiple elements of the same type) NetReflector will throw an exception! So the XSD would have to except either an attribute or an element – and I have no idea how to do that.

So to simplify things, most properties are defined as elements, even though they can also be attributes. There are a few exceptions, but these I have changed by name (and thus may be lost in future).

With these two limitations the XSD generation and the XSD itself is working :-) I have added all the tasks/publishers, triggers and related configuration – basically everything that I have imported into the code base. As I update the documentation I will also update the XSD.

In a future post I’ll talk about where I’m planning on taking the XSD and configuration in general for CruiseControl.NET, but for now, it’s time to finish the documentation!

To finish with, here are a couple of examples of the XSD in action (this is using Visual Studio 2008):

image

image

image

Of course, I’ll finish by mentioning that this is still a work in progress, but soon it will cover the entire “core” configuration.

Stay tuned…

Posted in CruiseControl.Net | Tagged: | Leave a Comment »

Security Documentation

Posted by Craig Sutherland on 11 December, 2009

A while ago I wrote about some scenarios for security. These were written as I was in the process of implementing security for CruiseControl.NET, so they were up-to-date at the time.

However, as I neared completion of security, I realised some things were not as clear as they should have been, so I changed a few things. These changes unfortunately broke the scenarios – in that the configuration that was produced was no longer correct :-(

Now, as part of the drive to update the documentation for CruiseControl.NET, I have revised and corrected these scenarios. Each scenario is based around a fictitious company or project and goes through the whole process of designing and implementing the security for that scenario.

They were designed to give an overview of what can be done with security, although they don’t cover all the possible scenarios (feel free to provide some more examples and I’ll write them).

Anyway, here are the updated scenarios:

Hopefully these will help in implementing security for CruiseControl.NET.

Posted in CruiseControl.Net, Security | Tagged: | Leave a Comment »

Timeline with Historical Data

Posted by Craig Sutherland on 10 December, 2009

After my last post I was asked if the new timeline plug-in works with existing data. The answer is yes – there were no server changes for this plug-in, it uses the existing server interfaces, it just provides a new UI on top the existing infrastructure.

Just to prove this works, I updated the installation at my work. This installation has been running since Apr 2008 (yes, before I started contributing to CC.NET). here is what the timeline looks like during one of our “busy” periods:

image

Again, I will repeat – this required no server changes! I did completely re-install the web dashboard for this plug-in, since it has a number of additional JavaScript and Image files that the package does not include (this “assumes” they are on the server). When we get around to doing some more work on the dashboard packages we can look at building a full package that includes all the additional files – but for now, I’m lazy ;)

Posted in CruiseControl.Net | Tagged: | 1 Comment »

Build Timeline

Posted by Craig Sutherland on 9 December, 2009

What’s Happening?

At my work we are playing around with a JavaScript widget called Simile Timeline (details on the widget are available at http://simile-widgets.org/wiki/Timeline). This is what provides the timeline in sites like http://www.ohloh.net. Basically, it provides a scrollable timeline, with events on it (these can be point events or durations). Clicking on an event will pop up a little “bubble” with extra details in.

Anyway, I thought that this is a nice fit for CruiseControl.NET – after all, builds are events in time. And since I need a change from working on documentation, I thought I’d take a look at what is involved in adding this to the dashboard.

Nice and Easy

Since this is a JavaScript widget, I downloaded the files and added them to the project. Next I added te plugin and action classes to the dashboard.

The action class performs two actions:

The first action is to generate the actual view. This is what the users see, so I added a status bar to provide extra details. This is a plain NVelocity template that generates some HTML. Additionally, there is a <script> section in it that initialises the timeline widget, loads the data and provides the status messages.

The second action is the data retrieval. The widget expects either an XML or JSON data file, so I choose XML (since it is already supported by the dashboard.) This file contains a list of events, the date they happened on, plus a title. For the dashboard, the title is just the status (success or failure), plus the build label.

And that’s all there really is to it. I added a few extra bits and pieces to try and make the user interface a bit more friendly. And like everything else, there is still some room for improvement. Currently clicking on a build just shows the date/time, the title plus a link to go to the view. In future it would be nice to have some extra details in this pop-up, but this will require some work on the back-end.

The Results

Here’s what the timeline view looks like:

image

Clicking on an event pops up the bubble:

image

And of course, the timeline can be scrolled:

image

That’s All Folks

So, that’s all there is to this plug-in. Nice and simple.

I personally like being able to see a timeline of events, what do other people think? If there is interest in this I’ll add it to the 1.5 release, otherwise it’ll wait until some undefined point in the future :-)

Posted in CruiseControl.Net | Tagged: | 2 Comments »

Documentation: Slow progress

Posted by Craig Sutherland on 8 December, 2009

As I recently posted, I’ve taken on the job of reviewing the documentation for CruiseControl.NET. We actually have a LOT of documentation, although from some of the comments I’ve seen we don’t always hit the mark.

At the moment I am working on the documentation for configuring the server – since this is where most people go initially. I am moving all the current comments from the wiki into the codebase as doc-comments, so hopefully in future other developers will see these and realise that they need to add documentation! But as you might realise, it takes time to import the documentation, generate the documentation, check it, fix any issues, re-generate it, check it, fix more issues, etc., etc.

Currently I have finished almost half the documentation (triggers, tasks/publishers, dynamic values) – although there is no end in sight yet! Once I’ve finished the server configuration, I’ll do the dashboard configuration (since that will be a similar process) and then take a break :-)

So, feel free to take a look at the new documentation. Let me know if there are any errors, or anything that could be added to make things clearer.

Happy reading…

Posted in CruiseControl.Net | Tagged: | Leave a Comment »

Documentation Update

Posted by Craig Sutherland on 7 December, 2009

Over the past few days I have been slowly moving the documentation into the code base so the automatic document generator can work. I have now managed to migrate all the tasks, publishers, triggers and related configuration, plus I have published the resulting documentation on the wiki.

Please take a look and see if there are any issues. Otherwise, I will continue slowly working my way through the documentation (source control blocks are next)…

Posted in CruiseControl.Net | Tagged: | Leave a Comment »