An Exciting New Task
A while back one of the other developers showed me an exciting extension to CruiseControl.NET – a conditional task plug-in (at http://ccnetconditional.codeplex.com/). This plug-in allows a user to define conditions for execution – with multiple conditions, alternate execution path and a few other nice features.
I got in touch with the original author (Lasse Sjørup) and he very kindly gave us permission to include it in the codebase for CruiseControl.NET. Unfortunately at the time we were preparing for the 1.5 release and were unable to include it (since we didn’t want to push out the release!)
However, the 1.5 release is pretty much there (maybe a few more bug fixes to add) and we have started on a 1.6 release. So I have spent a bit of time porting the plug-in over to the trunk, and as of now the conditional task can be used!
Some Examples
The task is very simple in the way it works – you specify the conditions to check and then the tasks to run if they pass or if they fail. The basic layout is:
<conditional>
<conditions>
<!– conditions to check –>
</conditions>
<tasks>
<!– tasks to run if the conditions pass –>
</tasks>
<elseTasks>
<!– tasks to run if the conditions fail–>
</elseTasks>
</conditional>
The nice thing about this task is both the tasks and the elseTasks elements are optional. If you want to run some tasks if some conditions are not met, you just include the elseTasks element – no need for a not condition! But I’m getting side-tracked.
Lasse has provided a base set of 9 conditions:
- And
- Or
- Build condition (ForceBuild or IfModificationExists)
- Status (successful, failed, exception, etc.)
- File exists
- Folder exists
- URL ping
- URL ping with header value
- Value comparison
You build up the conditions to check, and then define the tasks to call (these can be any task or publisher). For example, if we wanted to run different NAnt scripts based on either the build condition or the existence of a file, we could use the following:
<conditional>
<conditions>
<orCondition>
<conditions>
<fileExistsCondition>
<file>test.txt</file>
</fileExistsCondition>
<buildCondition>
<value>ForceBuild</value>
</buildCondition>
</conditions>
</orCondition>
</conditions>
<tasks>
<!– tasks to run if the conditions pass –>
</tasks>
<elseTasks>
<!– tasks to run if the conditions fail–>
</elseTasks>
</conditional>
And so on. It is possible to build up a very wide range of conditions using the existing conditions. Additionally, it is possible to use dynamic values with these conditions, expanding the range even more.
But Wait, There’s More…
If there is not a task that meets your needs, it is very easy to add more. Lasse designed the conditions around an interface – ITaskCondition. So it is a simple matter to extend the system and add condition plug-ins. This interface has the following definition:
public interface ITaskCondition
{
bool Eval(IIntegrationResult result);
}
It uses the standard NetReflector attributes (just like a task, publisher, trigger, etc.)
So not only has Lasse developed a brilliant task, he has made it so easy to extend (I already have a few ideas of new conditions to add
)
Documentation
As part of adding the task and the conditions I have also added the documentation to the wiki. The full documentation can be found at http://confluence.public.thoughtworks.org/display/CCNET/Conditional+Task. Let me know if you find any problems with it (I’ll take full responsibility for any mistakes in the documentation!)
A Final Word of Thanks
As you can guess I am really impressed with this plug-in. Again, many thanks to Lasse Sjørup for allowing us to include this in the CruiseControl.NET code.