RDoc and Hudson
This wasn’t easily findable the other day, so I’ll post this and see if someone else is saved a bit of digging.
RDoc is the Ruby way of generating documentation directly out of the source code and is a handy thing to have available and up-to-date when you have different people handling different layers of the product. (We’ll ignore how this breaks the concept of shared code ownership for the purposes of thing today.) Since the code changes constantly, the RDocs do as well and the only thing worse than no documentation is inaccurate documentation. Because of this, it makes sense to generate fresh docs each build with our CI server. I did this over the last couple days using Hudson
Installing the plugin
Everything in Hudson is a plugin, but there is not an official RDoc one. Focus in on the word official and then grab the unofficial RDoc plugin. This is a direct copy of the JDoc plugin with a couple fields changed (the comments still all say JDoc though). I closed the window I was doing this in, but I think it was as easy as:
adam:~ adam$ git clone git://github.com/juretta/hudson-rdoc-plugin.git
adam:~ adam$ cd hudson-rdoc-plugin
adam:hudson-rdoc-plugin adam$ mvn clean compile
adam:hudson-rdoc-plugin adam$ mvn hpi:hpi
You then upload it into Hudson (Manage Hudson, Manage Plugins, Advanced, Upload) and restart it. Uploaded plugins are automatically installed so you can use it right away.
Configure the jobs
Now when you go into one of your Ruby jobs you will see Publish RDocs as an option. Enable that and put in the location, relative to the job workspace root , where the RDocs will end up. For me, using svn, it was just trunk/doc.
The rake gem includes an RDoc task by default so in most cases just typing rake doc will generate your project’s RDocs. rake -T doc will tell you whether or not you have the magic already.
If you are missing the magic or have a special situation, then you will want to use rake’s RDocTask do handle things. We’ve got a bunch of stuff (that should be somewhere else, but aren’t) in the lib directory of a Rails project that we want docs for so I put a custom task in the project Rakefile.
namespace :doc do
Rake::RDocTask.new(:velo) do |rd|
rd.rdoc_files.include("lib/**/*.rb")
rd.rdoc_dir = "rdoc"
end
end
I recommend you keep it in the doc namespace to keep things organized.
Once you have figured out what your rake task is, add it to the list of tasks hudson is executing for your build and build the job. In theory you will end up with a directory under the job called ‘rdocs’.
Securing
Perhaps you are creating these solely for the benefit of internal or trusted persons; just having it floating in the wild is not really a good idea. Since these are html pages, install a web server on your hudson machine (if one doesn’t exist already) and lock it down. Using Apache, I did this in two different ways.
First I had to tell the server where everything was. Rather than copy it a second time somewhere into the server root I just aliased things around for each RDoc I wanted to display.
<VirtualHost *:80>
ServerAdmin adam.goucher@zerofootprint.net
DocumentRoot "/var/www"
ServerName hudson.zerofootprint.net
ErrorLog "/var/log/apache/error-docs.log"
CustomLog "/var/log/apache/access-docs.log" common
LogLevel debug
Alias /asclient /home/hudson/.hudson/jobs/ASClient/rdoc
<Directory "/asclient">
Options FollowSymLinks
AllowOverride All
Order allow,deny
Allow from all
</Directory>
Alias /ipsclient /home/hudson/.hudson/jobs/IPSClient/rdoc
<Directory "/ipsclient">
Options FollowSymLinks
AllowOverride All
Order allow,deny
Allow from all
</Directory>
</VirtualHost>
It’s displayed now, but we still have to secure it. There are a number of tutorials out on the internets about basic authentication, and the only sneaky thing I did was create the .htaccess file in Apache’s DocumentRoot and then symlink to it from every other rdocs directory. This way, if I change one file, they all get the change.
And that’s all it takes.
Notes
- If you job has a space in the title, create a symlink to it without spaces.
- RDocs are only published upon successful build, which makes sense