Friday, January 18, 2008

Continuous Documentation

Continous Integration (CI) is not a new topic anymore. It has been a proven method to make sure your code works as expected every single time you do a change to it. Usually a CI process focused on building a project (Deployment might involve more steps) involves steps like,

1. Detect changes to the source
2. Download the updated source from source control to the build machine
3. Compile the source and build the binaries
4. Run the unit test suite
5. Publish the result to relevant people

The additional step I'm going to focus in this posting is documentation. i.e To generate the documentation for the complete source automatically using the CI tool, which I prefer to call 'Continuous Documentation'. My focus will be on ways and technologies to achieve this in the Microsoft technology domain.

The most popular documentation generation tool for .Net is Sandcastle. The way to achieve our target is to write a Nant target which produces the documentation in either html or chm format and to call this Nant target at an appropriate time from CruiseControl.Net (CruiseControl.Net is the build scheduler while Nant is the actual builder).

Most of the learnings on how exactly to do this is from this article on code project. There were some discrepancies in that article with respect to latest SandCastle version and I'd like to emphasize on those points. (To keep the post short only important nant extracts are mentioned in the post it self. The complete Nant target will be attached for your convinience)

1. Compile your source with the additional 'doc' attribute to 'csc' (C-Sharp compile) nant target.

<csc target="library" debug="${debug}" output="${foo.dll.dir}\foo.dll" doc="${foo.dll.dir}\SPN.PredatorAPIDoc.xml" >

2. Copy a Sandcaslte configuration file from the default configurations that comes with Sandcastle. You just have to replace the default documentations comments xml with your own doc xml 'fooDoc.xml' generated from previous step. Sandcastle comes with 3 default configurations hana, vs2005 & prototype. I'm using vs2005 here. (Instead you can have the required sandcastle config file in your source and refer it as well)

3. Run the MrefBuilder to generate a basic reflection XML by introspecting on the assemply

<exec program="${sandcastle.mrefbuilder.exe}" workingdir="${sandcastle.workingdir}">
<arg value="..\${foo.dll.dir}/foo.dll" />
<arg value="/out:reflection.org1.xml" />
<arg value="/dep:..\foo.Lib/*.dll" />

4. Next step is to run a step of xmltransformations (using xsl) on this basic reflection xml from the preivious step
<exec program="${sandcastle.xsltransform.exe}" workingdir="${sandcastle.workingdir}">
<arg value="reflection.org1.xml" />
<arg value="/xsl:"{sandcastle.applyvsdocmodel.xsl}" />
<arg value="/out:reflection.org2.xml" />

Similar to above you need to run a few more transformations and you can also run some additional transformations as you wish. (Eg : FriendlyFileNames.xsl). There are many presentation transformations in ProductionTransforms subfolder in Sandcastle installation directory. I faced some difficulties getting all these transformation mentioned in the code project article to work. My approach was to refer the example MS Build script (<SandCastle_Install_dir>\Examples\sandcastle\build.proj) which was shipped with Sandcastle and to convert the transformations mentioned there to Nant.

This step (or series of steps) should result from a final reflection file called the reflection.xml

5. Now copy the other presentation helper directories (scripts, icons, styles) from Sandcastle_installation_dir/Presentation/vs2005 in to a subdir inside ${sandcastle.workingdir}.

6. Next you need to create some source files for Help compiler which generates a chm file. These files are

* hhp file - Html Help Project file
* toc.xml - Table of Contents file
* hhc file - Chm contents file out of toc
* hhk file - Chm index file from the final reflection xml

For all the above you will be using some kind of xml transformation (xsl) which comes with sandcastle.

7. And the grand final step is to use Html Help Workshop's hhc.exe help compiler to compile all above files in to a single chm file

<exec program="${hhc.exe}"

Finally you will have a chm file which is the compiled help file which can be distributed with your application.

Since documentation generations is usually a time-taking process I suggest you run this nant target as a nightly task. So you have the documentation getting updated each day as opposed to each check-in. Use the <triggger> block of CC.Net to schedule this documentation task as a separate CC.Net project which runs every night.

Having the documentation up-to-date like this helps your project in several ways.

1. You have a ready to pack deliverable without any extra effort at the end of the project
2. You can send the documentation for review very early
3. The development team can readily refer the documentation as and when new parts are added to the system
4. Encourages developers to document as and when they code

PS : The complete Nant script can be found here.
Post a Comment