Passing Dynamic Parameters: Part 2, CCTray
Static No More
In my last post (read it here) I modified the server component of CruiseControl.Net so dynamic parameters can be set for projects and tasks. However, there’s no point in allowing dynamic parameters if the end user can’t set them.
In this post I’ll modify CCTray so the user can set the dynamic parameters.
What Can the User Do?
The first part of allowing the user to set parameters is to find out what is allowed. This involves a call to the server to retrieve the list of parameters, and then displaying them.
The interface that allows connection to the server is ICruiseProjectManager. I’ve added a new method called ListBuildParameters(). The controller will call this method to see if there are any parameters. If so it will display them so the user can change them. Otherwise it will just perform a force build.
I also modified IProjectMonitor so it has the same method. This is because the controller doesn’t directly call ICruiseProjectManager, instead it uses this interface (as a pass-through layer). This also required modifying AggregatingProjectMonitor, ProjectMonitor and SynchronizedProjectMonitor (these all implement the interface).
The final step is to modify HttpCruiseProjectManager and RemotingCruiseProjectManager to actual populate the parameters list. Since RemotingCruiseProjectManager just uses .Net Remoting, this was nice and simple – just called the new method on ICruiseManager. HttpCruiseProjectManager is a bit harder since it also needs changes to the dashboard, so I’ll cover this in my next post.
Displaying the Parameters
Now I have the parameters, the next stage is to display them. I’ve added a new form that contains a PropertyGrid for the display and a couple of buttons.
The grid will show the parameters and allow the user to change them. Clicking on the build button starts the force build (using the controller) and passes in the parameters as a Dictionary<string, string>.
Now I would love to say it was nice and easy to display the parameters in the grid, but it wasn’t When I had built a project previously using .Net 1.1 I had used a ICustomTypeDescriptor implementation together with the PropertyGrid to allow some custom processing. This time, using .Net 2.0, I just couldn’t get it to work (the values were read-only, nothing I did would make them writable!)
Now the funny thing is, PropertyGrid works fine without the custom type descriptor – there is obviously some “special” processing going on to allow this to work (a CLR bug?) So I decided to generate my own property classes using System.Reflection.Emit. This is fairly simple to do, especially with the help documentation.
So now I have a rather hack way of displaying the parameters to the user, but it works:
In this example screen shot I have my three parameters, with nice display names and a description.
I’ve even generated the parameters with allowed values as enumerations so the dropdowns will pre-populate. And of course, since I generate the custom class the numeric values include validation.
Sending the Values
The final step in the process is to pass the parameters to the server. The new form already generates the parameters in a dictionary for the server, so it just needs to be passed on.
This also involved a change to ICruiseProjectManager and IProjectMonitor (and their associated implementations). I simply added a new parameter to the ForceBuild() to take in the dictionary and pass it on (yes, I will still need to modify HttpCruiseProjectManager when I work on the web dashboard.)
A New Dynamic World
With these changes in place the user can now pass on dynamic values to the server and perform “custom” builds
The final step in this project is the dashboard, so I’ll cover this in my final post in this series.