Using Templates to Track Outdated Content in a Documentation MediaWiki

Both my last and current jobs use MediaWiki for internal documentation. As always happens, some of this documentation will inevitably get out-of-date, or totally deprecated. As is also the case, many times when we’re looking for docs in the middle of an incident, we don’t have the time to go back and fix what’s wrong. So, I devised the following template/category system to help keep track of these problem pages.

First, create some templates that you will apply to the problem pages. I use three – one for totally deprecated pages, one for pages that need updating, and one for pages that just need cleanup. For the cleanup template, in the MediaWiki search box, enter “Template:Cleanup” and click “go”. You should be told that the page doesn’t exist, and given a link to create the page. Create it, and enter the following content:

<table class="metadata plainlinks mbox mbox-caution" style="">
<tr>
<td class="mbox-image">
[[Image:Cleanup.png]]
</td>
<td class="mbox-text" style="">'''This page needs to be cleaned up or reorganized.'''</td>
</tr>
</table>
 
<includeonly>[[Category:Pages Needing Cleanup]]</includeonly>

Now we create a category page for it, “Category:Pages Needing Cleanup”, with the content:

__HIDDENCAT__
 
This category is for pages that are mostly correct and just need minor corrections or reorganization.
 
'''To add pages to this category''', include the following at the '''TOP''' of the page:<br />
 
<code><nowiki><!-- REMOVE THIS TEMPLATE WHEN PAGE IS UPDATED-->
{{cleanup}}</nowiki></code>

and save the page.

Now there’s a few other changes we need to make. First, upload the Cleanup.png graphic, which I got from wikimedia.org here and uploaded as Cleanup.png.

If you refresh the Template:Cleanup page, you should now see the image. On a side note, “__HIDDENCAT__” on the category page prevents that category from showing up in the category list at the bottom of the pages we add to it, but this only works in MediaWiki 1.13 and up.

The last step is to add the MediaWiki mbox template and its dependencies. While I did this once before, I didn’t really remember the steps, but I found a post on Glynor’s blog that details them rather nicely:

  1. Enable the ParserFunctions extension. There are download and install instructions on the extension page, but you’ll want to enable string functions. To do this, include the extension in LocalSettings.php like:
    require_once( "$IP/extensions/ParserFunctions/ParserFunctions.php" );
    $wgPFEnableStringFunctions = true;
  2. Create a new page in your wiki called “Mediawiki:Common.css”, and paste in the content from MediaWiki.org MediaWiki:Common.css.
  3. Go to Wikipedia’s Special:Export page, and enter “Template:Ambox” in the box, check off “Include templates”, and export the template (and all dependencies) to a local XML file.
  4. Go to the “Special:Import” page of your wiki, and upload the XML file you just grabbed from Wikipedia. This will import the Ambox and mbox templates, as well as their dependencies.
  5. Now, if you go back and refresh the Template:Cleanup page you created, you should see the icon and a nice message box:

cleanup message box

Finally, add the template and category pages for update and deprecated:
Template:Update

<table class="metadata plainlinks mbox mbox-caution" style="">
<tr>
<td class="mbox-image">
[[Image:Warning.png]]
</td>
<td class="mbox-text" style="">'''This page is in need of updating. Some information on it may be out of date, and should not be relied on.'''</td>
</tr>
</table>
 
<includeonly>[[Category:Pages Needing Updates]]</includeonly>

Category:Pages Needing Updates

__HIDDENCAT__
 
This category keeps track of pages that need changes or updates.
 
'''To add pages to this category''', include the following at the '''TOP''' of the page:<br />
 
<code><nowiki><!-- REMOVE THIS TEMPLATE WHEN PAGE IS UPDATED-->
{{update}}</nowiki></code>

Template:Deprecated

<table class="metadata plainlinks mbox mbox-caution" style="">
<tr>
<td class="mbox-image">
[[Image:Critical.png]]
</td>
<td class="mbox-text" style="">'''The information on this page is badly out-of-date.''' It describes a system that is no longer in production or has drastically changed, and '''needs to be updated or rewritten'''.</td>
</tr>
</table>
 
<includeonly>[[Category:Deprecated Content]]</includeonly>

Category:Deprecated Content

 __HIDDENCAT__
 
This category keeps track of pages that are '''seriously old''' or otherwise describe systems/hosts/etc. that have seriously changed from what is described in the page.
 
 
'''To add pages to this category''', include the following at the '''TOP''' of the page:<br />
 
<code><nowiki><!-- REMOVE THIS TEMPLATE WHEN PAGE IS UPDATED-->
{{deprecated}}</nowiki></code>

And the download the two images – http://upload.wikimedia.org/wikipedia/commons/9/98/Ambox_deletion.png gets uploaded as Critical.png and http://upload.wikimedia.org/wikipedia/en/f/f4/Ambox_content.png gets uploaded as Warning.png.

That’s it. To use this, just add {{cleanup}}, {{deprecated}} or {{update}} to the top of a wiki article (adding the HTML comment before it is also recommended), and it will add the page to the appropriate category and show a nice message box at the top of the page:

Cleanup:
cleanup message box
Update:
update message box
Deprecated:
deprecated message box

I also add a link to the top of the main wiki page:

Things that need to be done: [[:Category:Pages Needing Updates|Pages Needing Updates]], [[:Category:Deprecated Content|Pages with Largely Deprecated Content]], [[:Category:Pages Needing Cleanup|Pages Needing Cleanup]], [[Special:WantedPages|Links to Nonexistent Pages]]

Documentation generation for web apps – PHP and JavaScript

Recently I’ve been making some changes to a relatively complex ePCR (electronic patient care report) program that I wrote for the ambulance corps. It’s a web application (available only on our LAN, of course) written in PHP, with a relatively large chunk of custom javascript to provide Ajax/DHTML functions. Most of the PHP code was already documented and processed with phpDocumentor (phpdoc) to generate API documentation. However, since so much of the functionality is DHTML-based, there was a lot of looking back to the JavaScript source to figure out what was called where.

My search for a true multi-language documentation generator was relatively fruitless. There’s doxygen but that needed a Perl helper script for javascript files. Since virtually all of the code, both PHP and JavaScript, is purely procedural, I was really only concerned about docblocks and the functions they precede.

Luckily, it occurred to me that JavaScript is pretty close in syntax to PHP, and I tend to write them with exactly the same style. A little research showed that phpdoc can more or less handle javascript code, with a few caveats:

  • The code needs to parse as PHP, so things like inline functions mess it up.
  • The default phpDocumentor ini file doesn’t recognize files with .js extensions.
  • The files need to have a <?php at the top.

Noting this, I wrote a small script that iterates through a directory of .js files, parses them line by line, pulls out only the function declarations (which, hopefully, don’t also have code on the same line) and docblocks, and writes the output (with a <?php at the top) to a same-named file in a different directory.

The script obviously requires phpdoc to be installed, and also requires you to edit the phpDocumentor.ini file (installed with PEAR on my system at /usr/share/php5/PEAR/data/PhpDocumentor/phpDocumentor.ini) and add a “js” line to the [_phpDocumentor_phpfile_exts] section to get phpdoc to recognize *.js files.

I was easily able to integrate this with a Makefile rule and create a single set of cross-linked phpdoc API docs including both JS and PHP files. I also added explicit package names (like “-PHP” and “-JS”) to keep things separated a little.

The script can be found at: http://svn.jasonantman.com/misc-scripts/js2phpdoc.php. It’s (obviously) free for any use, provided that you follow the license terms (leave copyrights intact, send modifications back to me, and update the changelog if you modify it).

My Makefile rule (which uses a temp directory to both keep the generated files separate from the source and keep the file paths as seen by phpdoc the same as the actual source):

.PHONY: docs

docs:
mkdir -p temp/js
bin/js2phpdoc.php js/ temp/js/
cp -r inc temp/
cp *.php temp/
phpdoc -c docs/default.ini
rm -Rf temp

Mediawiki Extension – Section Link To Top

While working on a particularly long documentation page in MediaWiki today, I came by a convenient little extension:

Section Link To Top

It adds a nice little “top” link next to the “edit” link in each section header. Very useful for long pages.

Putting the Why in Documentation

I work as a Linux Sysadmin (among many other non-official titles) in a small group that mainly provides services. We run wireless and student computing labs across a whole campus, but other than that (and most of that) is just back-end systems – web servers, RADIUS, DHCP, etc. As a result, I write no end-user documentation. I generally think of this as a blessing, since the people who read my documentation are people who think (more or less) like me.

However, I’ve just started writing the wiki page for a rather large system I developed. And in writing the docs, and thinking about what was missing from the (practically non-existent) documentation on the system I was replacing, it got me thinking a lot about the documentation writing process. Most of us have heard that there are two general types of documentation – end-user docs and developer (and I’m rolling SysAdmin in here) documentation. End-user docs tell someone how to use what we built. Developer docs tell people how to troubleshoot, fix, modify, and extend it. Usually.

But there’s one very important piece that’s missing from most developer-level documentation I’ve read: why it’s built the way it is. Sure, this isn’t applicable in all instances. This is obviously ignored by closed-source software developers when writing documentation for release. And I’m sure it’s ignored in some larger shops just out of fear that the interns will explain why they need to iterate a database result set. But for those of us who are designing and building systems, I’d argue that documenting the reasons behind our decisions is much more important than how-to-fix-it or how-to-rebuild-it documentation. Sure, it’s atrocious practice, but that can all be gleaned from examining a live system or backups. But when it comes time for the next person (or you or I, five years down the road) to re-design or drastically modify our creations, some documentation of the decisions we made – and the reasoning behind them – will be extremely useful.

Case in point: My latest project started as performance analysis of a large DHCP server using the Masney LDAP patch to ISC DHCPd. After over a week of performance testing and trying different configurations and theories (all of which I “documented” in my text file lab notebook), we ended up deciding to totally remove LDAP from the system, move to configuration files generated from MySQL, and keep everything (including the logs) in ramdisk. We found performance bottlenecks in both the LDAP communication and disk IO. We have the performance test output to prove it. We have the results of dozens of tests with different configurations, as well as a number of problems we identified with the LDAP patch. And from testing, we have a handful of issues identified and fixed in the new system, whose fixes aren’t exactly intuitive.

The previous system had pretty poor documentation, but even worse, it was only functional documentation – what the system does, and how it does it. There was no discussion of why the parsing script disregarded lines with a certain string in them, why the daemon is restarted every night, why LDAP was chosen in the first place, or any performance metrics (so we had no original as-intended baseline to compare against).

So for those of you designing systems and documenting them (you *do* document them, right?), please include why in your documentation. The next time someone needs to fix or tweak or re-engineer the system, they’ll be able to figure out what happens on line 123 of the init script themselves. But it might take them hours to figure out why it’s done, or why it’s done that way.

Web-based collaboration/documentation software

This question was posted both to the SAGE-members list (thread) and to ServerFault:

Looking for some advice here, as my search has turned up to be pretty fruitless.

My group (9 people – SAs, programmers, and two network guys) is looking for some sort of web tool to… ahem… “facilitate increased collaboration” (we didn’t use a buzzword generator, I swear). At the moment, we have an unified ticketing system that’s braindead, but is here to stay for political/logistical reasons. We’ve got 2 wikis (“old” and “new”), neither of which fulfill our needs, and are therefore not used very often. We’re looking for a free (as in both cost and open source) web-based tool.

Management side:
Wants to be able to track project status, who’s doing what, whether deadlines are being met, etc. Doesn’t want full-fledged “project management” app, just something where we can update “yeah this was done” or “waiting for Bob to configure the widgets”. TeamBox was suggested, but it seems almost too gimmicky (Twitter/Facebook ripoff?), and doesn’t seem to meet any of the other requirements that I see coming up:

Non-management side:
- flexible, powerful wiki for all documentation (i.e. includes good tables, easy markup, syntax highlighting, etc.)
- good full text search of everything (i.e. type in a hostname and get every instance anyone ever uttered that name)
- task lists or ToDo lists, hopefully about to be grouped into a number of “projects”
- file uploads
- RSS or Atom feeds, email alerts of updates

We’re open to doing some customizations (adding some features, notification/feeds, searching, SVN integration, etc.) but need something F/OSS that will run under Apache.

My conundrum is that most of the choices I’ve found so far fall into one of these categories:
- project management/task tracking with poor wiki/documentation/knowledge base support
- wiki with no task tracking support
- ticketing system with everything else bolted on (we already have one that we’re stuck with)
- code-centric application (we do little “development”, mostly SA work)

Any suggestions?

Or, lacking that, any comments on which software would be easiest to add the lacking features to (hopefully ending up with something that actually looks good and works well)?

I’m still awaiting responses from both SAGE and ServerFault, but I have a strong feeling that most of the suggestions will fall into one of the major categories I already identified, mainly:

  1. Project management/task tracking with poor wiki/documentation support (a la TeamBox)
  2. Wiki with no task tracking support
  3. Ticketing system with everything else added in (useless since we already have to use a different ticketing system).
  4. Something code-centric, i.e. built around a software development workflow, which isn’t us.

So, I have a very strong feeling that whatever solution we end up going with, we’ll need to spend quite a bit of time bolting on whatever else we need. Adding a full-featured wiki to another package isn’t going to be very easy… especially since TeamBox is written in RoR, and we’re mostly PHP guys.