I'm in the midst of moving things from Wordpress to Hugo and decided to push this as my main site instead of continuing to sit on it. If something's really broken here then you can go over to ww2.jamesgallagher.ie

Dexy & Asciidoc(tor): A Business Analyst’s documentation tool to look at

Like many a BA, I get cranky with Microsoft Word as a tool for writing requirements specification documents. ‘Track Changes’ functionality isn’t version control and very quickly becomes unwieldy. I also find that document formatting behaves inconsistently when you get into different sets of section formatting, even when you try to bend numbered lists to your will. I’ve also used IBM’s Rational DOORS in the past for documenting requirements and you get used to that idea of structured editing and establishing relationships between requirements. So, I decided one evening that I’d go to good old plain text and use a markup language for formatting so that I could have absolute control over my documentation.

which led to

Off I went with “What is dexy?” and the bit that stood out for me was:

Dexy makes it easier to create technical documents by doing the repetitive parts for you. Dexy provides a consistent interface to tools and scripts so you don’t have to run them manually. Your project’s dexy configuration keeps track of what to run, in which order, and with what parameters. This way, your whole process is captured so anyone can run it using one simple command and the results will be consistent.

From here I spent time choosing an appropriate markup language; Markdown is often the goto choice here but I found it somewhat limiting for my purposes and stumbled across Asciidoc. From there I ended up opting to use the Asciidoctor implementation of Asciidoc. This is where using dexy came into play; dexy ‘builds’ the Asciidoctor content along with any associated content (more on this later) and outputs to the format(s) that you want to distribute. It’s worth noting that you don’t have to use dexy to generate HTML (or even other formats) from Asciidoc[tor] as the respective distributions are both capable of producing HTML and other formats from their installed toolkits. dexy however brings everything together and becomes incredibly useful and time saving when you’re pulling together content from multiple sources.

Working off the excellent Asciidoc Writer’s Guide I started by producing an HTML document which I then distributed to colleagues in the office. Surprisingly a number of my engineering colleagues prefer to print out specs. HTML documents don’t always print nicely, especially when your documents get large and include cropped or shrunk wireframes. This is even the case if you use the Print to PDF or Save As PDF functionality that’s available. This made for a challenge and I’ll cover the solution (fop) in a separate post as this already really long.

At this point I decided to tackle another of the Word issues; version control. At the back of my mind I’d been thinking about git. This was partially inspired by blog posts on the use of git outside the world of coding and my own minimal use of github when adding some code to an open source project. Writing in plain text meant that git could be used as a quick and easy way to track changes and handle ‘releases’.

Next, I’ll go through how I’m using dexy as a tool for writing requirements documents / functional specifications.

I have a really simple Asciidoc template for the documents I produce that I use with a script when I start a new project. I call that from a shell script “createDexyProject.sh” with the name of the project as the only parameter:

``Like many a BA, I get cranky with Microsoft Word as a tool for writing requirements specification documents. ‘Track Changes’ functionality isn’t version control and very quickly becomes unwieldy. I also find that document formatting behaves inconsistently when you get into different sets of section formatting, even when you try to bend numbered lists to your will. I’ve also used IBM’s Rational DOORS in the past for documenting requirements and you get used to that idea of structured editing and establishing relationships between requirements. So, I decided one evening that I’d go to good old plain text and use a markup language for formatting so that I could have absolute control over my documentation.

which led to

Off I went with “What is dexy?” and the bit that stood out for me was:

Dexy makes it easier to create technical documents by doing the repetitive parts for you. Dexy provides a consistent interface to tools and scripts so you don’t have to run them manually. Your project’s dexy configuration keeps track of what to run, in which order, and with what parameters. This way, your whole process is captured so anyone can run it using one simple command and the results will be consistent.

From here I spent time choosing an appropriate markup language; Markdown is often the goto choice here but I found it somewhat limiting for my purposes and stumbled across Asciidoc. From there I ended up opting to use the Asciidoctor implementation of Asciidoc. This is where using dexy came into play; dexy ‘builds’ the Asciidoctor content along with any associated content (more on this later) and outputs to the format(s) that you want to distribute. It’s worth noting that you don’t have to use dexy to generate HTML (or even other formats) from Asciidoc[tor] as the respective distributions are both capable of producing HTML and other formats from their installed toolkits. dexy however brings everything together and becomes incredibly useful and time saving when you’re pulling together content from multiple sources.

Working off the excellent Asciidoc Writer’s Guide I started by producing an HTML document which I then distributed to colleagues in the office. Surprisingly a number of my engineering colleagues prefer to print out specs. HTML documents don’t always print nicely, especially when your documents get large and include cropped or shrunk wireframes. This is even the case if you use the Print to PDF or Save As PDF functionality that’s available. This made for a challenge and I’ll cover the solution (fop) in a separate post as this already really long.

At this point I decided to tackle another of the Word issues; version control. At the back of my mind I’d been thinking about git. This was partially inspired by blog posts on the use of git outside the world of coding and my own minimal use of github when adding some code to an open source project. Writing in plain text meant that git could be used as a quick and easy way to track changes and handle ‘releases’.

Next, I’ll go through how I’m using dexy as a tool for writing requirements documents / functional specifications.

I have a really simple Asciidoc template for the documents I produce that I use with a script when I start a new project. I call that from a shell script “createDexyProject.sh” with the name of the project as the only parameter:

``

That sets up everything I need in my current working directory. When I get around to it I’ll update the script to do the initial commit after the dexy setup, for now I’m lazy and this works :)

Looking at the dexy.yaml file is where you start to see the dexy smarts:

```Like many a BA, I get cranky with Microsoft Word as a tool for writing requirements specification documents. ‘Track Changes’ functionality isn’t version control and very quickly becomes unwieldy. I also find that document formatting behaves inconsistently when you get into different sets of section formatting, even when you try to bend numbered lists to your will. I’ve also used IBM’s Rational DOORS in the past for documenting requirements and you get used to that idea of structured editing and establishing relationships between requirements. So, I decided one evening that I’d go to good old plain text and use a markup language for formatting so that I could have absolute control over my documentation.

which led to

Off I went with “What is dexy?” and the bit that stood out for me was:

Dexy makes it easier to create technical documents by doing the repetitive parts for you. Dexy provides a consistent interface to tools and scripts so you don’t have to run them manually. Your project’s dexy configuration keeps track of what to run, in which order, and with what parameters. This way, your whole process is captured so anyone can run it using one simple command and the results will be consistent.

From here I spent time choosing an appropriate markup language; Markdown is often the goto choice here but I found it somewhat limiting for my purposes and stumbled across Asciidoc. From there I ended up opting to use the Asciidoctor implementation of Asciidoc. This is where using dexy came into play; dexy ‘builds’ the Asciidoctor content along with any associated content (more on this later) and outputs to the format(s) that you want to distribute. It’s worth noting that you don’t have to use dexy to generate HTML (or even other formats) from Asciidoc[tor] as the respective distributions are both capable of producing HTML and other formats from their installed toolkits. dexy however brings everything together and becomes incredibly useful and time saving when you’re pulling together content from multiple sources.

Working off the excellent Asciidoc Writer’s Guide I started by producing an HTML document which I then distributed to colleagues in the office. Surprisingly a number of my engineering colleagues prefer to print out specs. HTML documents don’t always print nicely, especially when your documents get large and include cropped or shrunk wireframes. This is even the case if you use the Print to PDF or Save As PDF functionality that’s available. This made for a challenge and I’ll cover the solution (fop) in a separate post as this already really long.

At this point I decided to tackle another of the Word issues; version control. At the back of my mind I’d been thinking about git. This was partially inspired by blog posts on the use of git outside the world of coding and my own minimal use of github when adding some code to an open source project. Writing in plain text meant that git could be used as a quick and easy way to track changes and handle ‘releases’.

Next, I’ll go through how I’m using dexy as a tool for writing requirements documents / functional specifications.

I have a really simple Asciidoc template for the documents I produce that I use with a script when I start a new project. I call that from a shell script “createDexyProject.sh” with the name of the project as the only parameter:

``Like many a BA, I get cranky with Microsoft Word as a tool for writing requirements specification documents. ‘Track Changes’ functionality isn’t version control and very quickly becomes unwieldy. I also find that document formatting behaves inconsistently when you get into different sets of section formatting, even when you try to bend numbered lists to your will. I’ve also used IBM’s Rational DOORS in the past for documenting requirements and you get used to that idea of structured editing and establishing relationships between requirements. So, I decided one evening that I’d go to good old plain text and use a markup language for formatting so that I could have absolute control over my documentation.

which led to

Off I went with “What is dexy?” and the bit that stood out for me was:

Dexy makes it easier to create technical documents by doing the repetitive parts for you. Dexy provides a consistent interface to tools and scripts so you don’t have to run them manually. Your project’s dexy configuration keeps track of what to run, in which order, and with what parameters. This way, your whole process is captured so anyone can run it using one simple command and the results will be consistent.

From here I spent time choosing an appropriate markup language; Markdown is often the goto choice here but I found it somewhat limiting for my purposes and stumbled across Asciidoc. From there I ended up opting to use the Asciidoctor implementation of Asciidoc. This is where using dexy came into play; dexy ‘builds’ the Asciidoctor content along with any associated content (more on this later) and outputs to the format(s) that you want to distribute. It’s worth noting that you don’t have to use dexy to generate HTML (or even other formats) from Asciidoc[tor] as the respective distributions are both capable of producing HTML and other formats from their installed toolkits. dexy however brings everything together and becomes incredibly useful and time saving when you’re pulling together content from multiple sources.

Working off the excellent Asciidoc Writer’s Guide I started by producing an HTML document which I then distributed to colleagues in the office. Surprisingly a number of my engineering colleagues prefer to print out specs. HTML documents don’t always print nicely, especially when your documents get large and include cropped or shrunk wireframes. This is even the case if you use the Print to PDF or Save As PDF functionality that’s available. This made for a challenge and I’ll cover the solution (fop) in a separate post as this already really long.

At this point I decided to tackle another of the Word issues; version control. At the back of my mind I’d been thinking about git. This was partially inspired by blog posts on the use of git outside the world of coding and my own minimal use of github when adding some code to an open source project. Writing in plain text meant that git could be used as a quick and easy way to track changes and handle ‘releases’.

Next, I’ll go through how I’m using dexy as a tool for writing requirements documents / functional specifications.

I have a really simple Asciidoc template for the documents I produce that I use with a script when I start a new project. I call that from a shell script “createDexyProject.sh” with the name of the project as the only parameter:

``

That sets up everything I need in my current working directory. When I get around to it I’ll update the script to do the initial commit after the dexy setup, for now I’m lazy and this works :)

Looking at the dexy.yaml file is where you start to see the dexy smarts:

```

The syntax for dexy.yaml is explained on the dexy site so I won’t get into here but there are some notable features that make this a must have tool for me.

  • My source Asciidoc file is processed twice here, through the dexy jinja and asciidoctor filters. The default output is HTML so I don’t have to specify that. You’ll see in the second block that I’ve specified x at the end of the chain which is short for XML; Docbook XML in fact

  • I use Docbook XML as an intermediate format for outputting a reasonably well formatted PDF

  • For the HTML output I can specify a stylesheet to apply
  • I can specify a Python script that will get executed by the dexy Python filter and have it’s output included in my final document
  • My source images and other assets get included in the generated output i.e. I can deploy the whole lot via dexy if I wanted.

My use of git is the next piece I want to run through. Simply by committing to git as I work gives me powerful change management as I write. However, as specification documents change you want to be able to communicate a summary of changes with each “release” of the document. I initially started out with the idea that the master branch would always hold the latest released documentation and that each version would have it’s own branch which I would then merge into master. This turned out to be less than optimal for me and I switched to tagging my release versions; 1.0, 1.1, etc. Both approaches allowed me to query git using the GitPython library and retrieve the changes (git commits) between tagged versions. I could then generate a change history table to be inserted into the final output. This is what change_control.py does. In my Asciidoc source file I just add the lines:
== Change History</p> <p>{{ d[‘change_control.py|py’] }}

    <p>
      which dexy executes and includes in the output.
    </p>

    <p>
      First up, a word of warning; I&#8217;m not a good programmer. The Python script I&#8217;ve written to build the change control table is pretty rough stuff. However, here it is:<br /> <code>import re&lt;br />

import time<br /> from inspect import getmembers<br /> from pprint import pprint<br /> from git import *</p> <p>def renderChangeTable(dict, changeDates):<br /> if len(dict) > 0:<br /> table = “[cols=‘10,10,80’, options=‘header’]\n\n|===\n|Version\n|Date\n|Description\n\n”<br /> keys = sorted(dict.keys())<br /> for key in keys:<br /> if (str(key)).find(‘raft’) == -1:<br /> table += “\n|” + key + “\n|” + formattedTime(changeDates[key]) + “\na|” + dict[key] table += “\n|===”<br /> return table<br /> else:<br /> return ‘[big]##Unversioned - Drafting##’</p> <p>def formattedTime(i):<br /> lt = time.localtime(i)<br /> return time.strftime(“%d/%m/%y”, lt)</p> <p>repo = Repo(“./”)<br /> assert repo.bare == False</p> <p># Get a list of all the tags and their associated commit date<br /> tags = repo.tags<br /> tagdict = {}<br /> changeDates = {}<br /> for t in tags:<br /> tagdict[t.commit.committed_date] = t<br /> changeDates[str(t)] = t.commit.committed_date</p> <p># Get all the relevant commits<br /> a = repo.iter_commits()<br /> allcommits = sorted(a, reverse=True)<br />

strip the merge requests and reverts<br />

for a in allcommits:<br />

print str(a.parents) + “:” + a.message<br />

if len(a.parents) <> 1:<br /> allcommits.remove(a)<br /> elif ‘This reverts commit’ in a.message:<br /> allcommits.remove(a)</p> <p># Associate the commit history (as Commit objects) with the relevant tag (A tag will have the commits which precede it and follow the previous (by date) tag)<br /> tag_commit = {}<br /> for t in sorted(tagdict):<br />

print str(t) + “:” + tagdict[t]

t_list = [] for c in sorted(allcommits):<br /> # print str(t) + “:” + str(c.committed_date) + “:” + c.message<br /> if c.committed_date <= t: t_list.append© allcommits.remove© tag_commit[tagdict[t]] = t_list

print str(t) + “:” + str(tag_commit[tagdict[t]]) + str(len(t_list)) + “\n”

Squash the commit message for all the Commit objects into a single string

tag_commit_messages = {} for t in sorted(tag_commit): for m in sorted(tag_commit[t]): if tag_commit_messages.has_key(str(t)): tag_commit_messages[str(t)] = “* “ + m.message + tag_commit_messages[str(t)] else: tag_commit_messages[str(t)] = “* “ + m.message

print tag_commit_messages

print renderChangeTable(tag_commit_messages, changeDates)

        <p>
          That's basically it. I'll go through a worked example and generating a PDF in another post as this one's unwieldy enough as it is.
        </p>
comments powered by Disqus