Archive

Posts Tagged ‘Documentation’

CruiseControl.NET–vNext: Some Design Decisions

25 December, 2010 1 comment

Like any project we need to make some design decisions around various components and patterns. For the next version of CruiseControl.NET I have made some decisions so it’s best that these are communicated.

Note: This post is a technical post – it you don’t care about the inner workings of vNext then it can be ignored.

First I believe that we should be doing TDD for vNext. Everything that is checked in should have working unit tests that prove that it works the way it should. This has two main benefits for us:

  1. We have a better idea of what we are trying to build
  2. We have a better safety net for when things change

There are additional reasons why TDD is good but for me these are the main two – especially the second one! I know things are going to change in the future (just look at how much they have changed for the current version) so having the safety net makes it so much easier for us.

Based on this decision I think we should be using an IoC container for wiring everything up. In the current version there is no consistent way of getting dependent class instances. For example for getting the file system interface we have three or four different ways of doing it. As you can imagine this makes things very confusing! So for vNext everything will use IoC for resolution. This also helps with TDD as we can abstract the various external dependencies behind interfaces and then mock them as required.

Based on these two patterns there are a number of choices we have for third party libraries to assist.

For TDD we will use NUnit. This is what CruiseControl.NET currently uses so people are familiar with it and it is one of the most popular unit testing frameworks, plus it is open source. To help with mocking we will use Moq. We’ve tried both NMock and Rhino.Mocks in the current version but both of them have their challenging areas. I’ve used Moq extensively in my jobs and I’ve found it easy to use. While it does have some challenging areas on the whole I’ve found it easier to use than the other mocking frameworks. And again it is open source (we try to use open source where possible as it’s not always possible for people to get licenses to commercial products.)

For IoC we’ll use Ninject. There is no particular reason why – I asked people for their preferences a while ago and didn’t get a consistent answer. I’ve used Ninject before and liked it, plus who can dislike a ninja-themed product Winking smile

Another important part of the system is logging – this provides a picture of what is happening inside the system – especially on systems that don’t have source code. Currently we use log4net but this is not maintained anymore. So instead we’ll change to NLog. Jaroslaw has done an excellent job of making NLog simple and easy to use and configure. It pretty much has the same functionality as log4net plus more.

Finally I’m going to change the XML parser we are using. As mentioned earlier we are using NetReflector but this is pretty much dead now.  So instead we’ll go with XAML and the .NET classes for it. System.Xaml provides a lot of the base functionality we need for parsing XML and generating an object tree. In addition it provides a number of extension points for going beyond the base functionality. In some future posts I’ll describe how we can extend the base functionality to tie in with IoC, logging, etc.

Customizing CruiseControl.NET

One of the challenges for any open source project is writing and maintaining documentation, and CruiseControl.NET is no exception (something to do with the techies’ perception that documentation is less fun than coding?) I’ve posted previously on some of the improvements I have added to the build process for CruiseControl.NET to automatically generate documentation about configuring the server.

At the same time I started writing what was to be a comprehensive document on customizing CruiseControl.NET (i.e. extending it beyond what is in the box.) Unfortunately life interrupted and the documentation got shelved (along with any free time I had to do open source :-( )

However Ruben reminded me about it and suggested that I post what I have done, so I have trimmed the scope of the document to just the server-side (e.g. either ccnet.exe or the service) and then tried to make sure it is reasonably complete. The document can be accessed at http://csut017.files.wordpress.com/2010/07/customisingcruisecontrol-net.pdf.

PS, for those who are wondering why I’m not writing much it is because I have returned to university, both as a job and for study, which means I won’t have much spare time until the end of the year (since I’m in New Zealand our academic years match the calendar years.)

Categories: CruiseControl.Net Tags:

Automating the Documentation

Introduction

I have finally finished putting the last pieces in place for automating the documentation for CruiseControl.NET. This means that once Dave has put the pieces onto the server, the documentation will be automatically generated every time the code is updated :-)

This post is a quick summary of what is involved on the server side. The following posts describe what I have already built for the documentation generator:

And in this post I will describe how I added the tool to CruiseControl.NET.

Some Tidying Up

First off, I did some tidying up within the documentation generator. Previously it expected the arguments in a set order. Unfortunately this made it harder to integrate with CC.NET. Additionally, it did not generate any log file – it just displayed all the details to the console.

The first change was to use the OptionSet class from the Remote project (this actually came from Mono originally). This allowed me to quickly and easily add argument parsing to the tool. Now all of the arguments have a prefix and can be specified in any order.

For example, the generation command line went from:

Console.exe generate ..\..\..\..\..\project\Remote\bin\Debug\ThoughtWorks.CruiseControl.Remote.dll documentation

to

Console.exe -c=generate -s=..\..\..\..\..\project\Remote\bin\Debug\ThoughtWorks.CruiseControl.Remote.dll -o=documentation –xsd

While this is now a bit longer, it means the arguments can be specified in any order!

Second, I added a switch to generate a log file. When this switch is set the output will be sent to a log file (in an XML format) instead of the console. This log file also contains the type of information (debug, info, warning or error) plus the date and time.

With these changes, the tool is now ready to be integrated with the main build.

Preprocessing

Before the tool can be run there needs to be some pre-processing. First, the tool needs to be compiled – it is only included as source code in the repository. This is done using a NAnt build script and is very similar to how the main solution is built.

Additionally the NAnt script also does some clean up. This clean up involves deleting the previous log files. If this step is omitted then a failed build would get the logs from the previous successful build!

Finally the NAnt script moves the pages.xml file from the project trunk to the location where the tool expects it.

Now with all this done, the tool can generate and publish the documentation.

Calling the Tool

Calling the tool is really easy, just need to use the exec task. The following is how this task has been configured for generation:

<exec>
  <description>Generate the documentation for the Remote project</description>
  <executable>Tools\docGenerator\Console\bin\Debug\Console.exe</executable>
  <buildArgs>-c=generate -s=Build\Remote\ThoughtWorks.CruiseControl.Remote.dll -o=wiki -l=doc-remote.log</buildArgs>
</exec>

The baseDirectory setting has been omitted, so this will default to the project working directory (more on this below). This means all the paths are relative to the repository trunk.

The executable element tells CC.NET where to find the tool – since it has been compiled previously we tell it to look in the debug folder.

The buildArgs element is the arguments that I described above, except with the log file specified. The log file is being used so we can import the results into the build log.

And that’s all there is to it. The other exec tasks are similar, expect with different buildArgs. The only one that is very different is the publishing. This is because it requires a password and username and we don’t want everyone to see it! To get around this we added a batch file with the password and username in it, and all the rest of the arguments are passed though (I’ll write a post on this in future.)

The Final Touches

The final touches (or first depending on your thinking) is to add the project to the configuration. I decided to add this as a new project, so it can run independent of the main build.

The project has the same workingDirectory as the build project, but is in a different queue and has a different artefactDirectory (the different artefactDirectory is required to prevent cross-contamination of the build logs!) There is no source control block, as the code will have already been downloaded by the main project. It contains the NAnt script task and the four exec tasks. Finally, the publishers section merges the external logs and generates the build log (via xmlLogger).

And to trigger the project I added a forcebuild task to the main project. This will fire the documentation project when the build has finished (but before the publishers.)

And that’s all there is to it! In all, it took me a couple of hours to set this all up, but that also involved committing changes to the repository and generating entire builds of CC.NET (not a fast process!)

So, in the end, this is the completed project:

<project name="CCNet-Doc">
  <queue>Documentation</queue>
  <workingDirectory>e:\sourcecontrols\sourceforge\ccnet</workingDirectory>
  <artifactDirectory>e:\download-area\CCNet-Documentation\1.5.0</artifactDirectory>
  <tasks>
    <!-- Prepare for the documentation -->
    <nant>
      <description>Setup for documentation generation</description>
      <executable>Tools\NAnt\NAnt.exe</executable>
      <buildFile>docPrep.build</buildFile>
      <buildArgs>-listener:CCNetListener,CCNetListener</buildArgs>
      <targetList>
        <target>all</target>
      </targetList>
      <buildTimeoutSeconds>1000</buildTimeoutSeconds>
    </nant>

    <!-- Generate the documentation for the three projects -->
    <exec>
      <description>Generate the documentation for the Remote project</description>
      <executable>Tools\docGenerator\Console\bin\Debug\Console.exe</executable>
      <buildArgs>-c=generate -s=Build\Remote\ThoughtWorks.CruiseControl.Remote.dll -o=wiki -l=doc-remote.log</buildArgs>
    </exec>
    <exec>
      <description>Generate the documentation for the Core project</description>
      <executable>Tools\docGenerator\Console\bin\Debug\Console.exe</executable>
      <buildArgs>-c=generate -s=Build\Core\ThoughtWorks.CruiseControl.Core.dll -o=wiki -l=doc-core.log</buildArgs>
    </exec>
    <exec>
      <description>Generate the documentation for the WebDashboard project</description>
      <executable>Tools\docGenerator\Console\bin\Debug\Console.exe</executable>
      <buildArgs>-c=generate -s=Build\WebDashboard\ThoughtWorks.CruiseControl.WebDashboard.dll -o=wiki -l=doc-dashboard.log</buildArgs>
    </exec>
    <exec>
      <description>Publish the documentation</description>
      <executable>E:\tools\docGen.bat</executable>
      <buildArgs>-c=publish -o=http://confluence.public.thoughtworks.org/rpc/soap-axis/confluenceservice-v1 -s=wiki\pages.xml -l=doc-publish.log</buildArgs>
    </exec>
  </tasks>
  <publishers>
    <!-- Merge all the files -->
    <merge>
      <files>
        <file>doc-remote.log</file>
        <file>doc-core.log</file>
        <file>doc-dashboard.log</file>
        <file>doc-publish.log</file>
      </files>
    </merge>
    <xmllogger/>
  </publishers>
</project>

Hopefully this will be helpful to someone else as well :-)

Categories: CruiseControl.Net Tags:

Documentation: Automated

9 January, 2010 4 comments

Too Lazy

One of the things I dislike doing is more work than I need to. After all, with computers, we can automate all the tiresome repetitive tasks, so why do them manually?

For the configuration documentation in CruiseControl.NET, I wrote a simple documentation generator. This takes the DLL for a project, plus the XML doc-comment files and generates a set of .wiki files that contains the documentation:

image

This ensures that:

  1. The formatting is consistent
  2. Everything is covered
  3. The process is repeatable

While this is nice and easy, it stops short. The problem is these .wiki files are not where they need to be. People don’t look at these files, they look at the web site! So the process really needs to take these files (which are intermediate output) and publish them to the web site.

WSDL to the Rescue

Well, not really WSDL, but the web service interface on the Confluence web site. The Confluence Wiki has a Remote API that is exposed via a WSDL definition, so we can use that for updating pages in the wiki. SO the process now changes to:

image

I have used the same program, but changed it has it also has a publish mode. This publish mode takes one or more wiki pages and uploads it to the web site.

But there is also another file in the picture – Confluence Mappings – what does this do? The problem is not all the pages in the wiki have the same title as the configuration element – some are slightly different (don’t ask me why, just accept that they are!) The mappings file tells the publisher which wiki document is loaded to which page in the web site.

But Wait, There’s More

Just like the TV ads, this application has one more trick up its sleeve. We need to get the Confluence mappings from somewhere, and where better but the web site itself. So the program can download the list of all the pages and update the file:

image

This mode pulls the list of all the pages from the web site and stores them in the mappings file. Someone then needs to go through and manually add the mappings to the files (yes, it is not automated – yet!)

At the moment, the pages need to exist within the web site, if they don’t they cannot be added, this will still be a manual process. The same also happens for deleted pages – the file needs to be manually edited to delete the file.

So, this now provides an almost completely automated process for generating documentation and publishing it :-)

Some Nuts and Bolts

So, how do these processes work?

For the publishing the file is loaded and parsed into an XDocument. The process then goes through and do the following:

  1. Check for a mapped file
  2. Make sure the file exists
  3. Downloads the page from the wiki
  4. Compares for differences
  5. Upload the file

If any of the steps fail (e.g. no file, no page, no differences), the item is skipped and the next item is handled. As you can imagine, because each page is downloaded this process can be a bit slow, especially over a slow connection, but it is still faster than a manual process (especially when a lot of pages have been changed!)

The list is even simpler, it downloads the list of pages and adds any new pages to the file. Because this is a single API call it is nice and fast!

Where To From Here?

As you can imagine, this utility is still pretty basic, although it has grown more than I expected! We will keep refining the documentation being generated, and maybe even look at speeding up the publishing, but in general I am not planning any more big changes to this tool.

Instead, I would like to look at adding this to the build process, as this would ensure that the documentation is always up-to-date. As such, we would probably need to tidy up the reporting a bit to make it easier to integrate into CC.NET. But this would certainly make the documentation both easier to publish and more up-to-date :-)

What do you think?

Categories: CruiseControl.Net Tags:

Documentation: Server Configuration Completed

17 December, 2009 1 comment

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 :-)

Categories: CruiseControl.Net Tags:

CruiseControl.NET XSD – Second Attempt

12 December, 2009 3 comments

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…

Categories: CruiseControl.Net Tags:

Security Documentation

11 December, 2009 Leave a comment

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.

Documentation: Slow progress

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…

Categories: CruiseControl.Net Tags:

Documentation Update

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)…

Categories: CruiseControl.Net Tags:

Documentation: Some Nuts and Bolts

4 December, 2009 1 comment

Previously I wrote about how I’ve been changing the documentation in CruiseControl.NET so it is now inline with the code. In my last post on the topic (read it here) I talked about the changes to the code base to allow automatic code generation. The next question is how to actually generate the documentation?

First and foremost, the code needs to be compiled. This will generate the dll, a pdb file and (now) an xml file. The first file is the actual binary, the second is the debug information and the third is all the document comments from the code base. Of these three files the documentation generator uses the binary and the xml.

Additionally, projects can have dependencies on other projects that contain information necessary for documentation. As an example the core project has a dependency on the remote project. This project contains definitions for many types which can be part of the configuration. Therefore, in order to generate the documentation, these files are needed as well.

So for the core project, the files that are needed are:

  • ThoughtWorks.CruiseControl.Core.dll
  • ThoughtWorks.CruiseControl.Core.XML
  • ThoughtWorks.CruiseControl.Remote.dll
  • ThoughtWorks.CruiseControl.Remote.xml

The good news, if you build the solution these files will all be automatically generated :-)

Next, there is a new project added to the tools folder called docGenerator (a nice simple name!) At the moment this is a C# project, only the source code is in Subversion. So the next step is to compile this project. Once this has finished, the documentation can be generated.

Note: docGenerator only needs to be rebuild if there are any changes to its code. Otherwise this step can be skipped.

docGenerator is a command-line tool. It has one required parameter – the assembly to document, and one optional parameter – the output location. If the output location is omitted the wiki files will be put in a time stamped directory underneath the current directory.

For example, here is how I run it:

image

This generates a set of files into C:\Temp\output:

image

Each of these files is a plain text file containing the wiki mark-up:

image

From here it is a simple matter of copying and pasting into the wiki – and making sure everything looks ok :-)

Categories: CruiseControl.Net Tags:
Follow

Get every new post delivered to your Inbox.