本エントリは、次のAdvent Calendarのために書かれたものです。

取り扱う内容

株式会社ALBERTのシステム開発部では、ドキュメンテーションツールであるSphinxを積極的に活用しています。

Sphinxの導入、利用そのものは簡易に行うことができるのですが、開発部でチームとして運用するためにはいくつかの困難がありました。

そんな幾重にも張り巡らされた困難を乗り越えて、2013年11月頃から本格的に運用が出来ているなぁ、と実感するに至ったので、今回は2013年の総決算としてその変遷を綴ります。

関連資料

Sphinxとわたし

今日に至までの変遷。

  1. 2012年末頃にSphinxについて知る。
  2. 2013年2月、に社内で1人で検証してみる。数式やダイヤグラムなどがさくさく書けることを知る。マイブームに。
  3. 開発チームへの展開を目論むも、運用について不安を抱く。
  4. 自分探しの旅へ出る。
  5. 2013年6月、社内のエンジニアリング勉強会でSphinxがとり上げられたのを契機に、マイブーム再燃。
  6. 同月、だいたい「SphinxをMarkdownで使い隊 - SlideShare」に書いた内容を思いつき、実践してみる。
  7. 2013年7月、限定的に社内で利用し始められる。
  8. 2012年8月2日、ドラゴンクエストX発売。
  9. 同月、本格的に社内で利用し始められる。

Sphinxのチーム運用の3つの壁

Sphinxは優れたドキュメンテーションツールであることは言うまでもありませんが、チームで運用する成果物を企業の資産として扱うことを考えると少し及び腰になってしまうのも事実です。

Sphinxのチーム運用には以下の3つの壁が存在すると考えています。

  • restructuredTextの壁
  • ビルドは誰がする?の壁
  • 運用ルールの策定の壁

少し細かく見ていきます。

restructuredTextの壁

restructuredText(以下reST)は表現力に富んだ良い軽量マークアップ言語です。従ってreSTが殊更難しいとか、使いにくいということを主張するつもりはありません。ただ、Markdownではないということだけが問題なのです。

Markdownは、GithubQiitaなどでも採用されている、軽量マークアップ言語のデファクトスタンダートと言えます。2013年6月からBacklogがMarkdown対応になったことを喜んだ人もいるのではないでしょうか。

とはいえ、世の中には既に多くの記法が存在していて、社内では主に以下のようなものが利用されていました。

  • Redmineのtextile記法
  • PukiWikiのPukiWiki記法
  • BacklogのBacklog記法(これはMarkdown対応により統一)
  • GithubQiitaなどのMarkdown記法

全てを統一できれば良いのですが、歴史的経緯により統廃合の容易でないシステムもあり、上記に加えてさらいreSTの学習と運用、となるとコストもばかになりません。

ミクロな視点では「それくらい覚えれば良いじゃないか簡単だし」という考えも一理あるのですが、チームでの継続的な運用という視点を持つと、敷居は低い方が良い、方法は統一されているほうが良い、と考えることもできます。

ビルドは誰がする?の壁

Sphinxでは、reST記法で書かれたドキュメントをバージョン管理ツールで管理し、 make html でHTML化したものをブラウザでプレビューするというのがベーシックな使い方の一つです。その make html を誰がどのタイミングで実行するか?ということを考えるのが 第二の壁です。

運用ルールの策定の壁

Sphinxに限ったことではないですが、チームで作成するドキュメントにはフォーマットが存在します。Sphinxの場合、ベースはテキストファイル、軽量マークアップ言語のため、ある意味コーディング規約とも言えます。

  • 見出しの作成ルール
  • 目次(Table of Contents、以下 toc)の作成ルール
  • 注釈の作成ルール

などがあるかと思います。これが第三の壁。

Markdownで書く

reSTの壁を突破するため、MarkdownでSphinxを使いたい。という内容をまとめたのが上述の「SphinxをMarkdownで使い隊 - SlideShare」です。

スライドの内容の通り、Pandocというドキュメント変換ツールを利用します。ダイジェストで書くと

  • 書くのはMarkdown
  • バージョン管理していくのもMarkdown
  • PandocがMarkdownをreSTへ変換する
  • SphinxがreSTを利用する

上記の通りです。

ビルドは自動で行う

ドキュメントはWebブラウザで閲覧したいですよね。SphinxでHTMLファイルを生成する場合、所定のディレクトリで make html を実行してHTMLファイル一式をビルドする必要があります。

この作業を、リポジトリへのプッシュのタイミングで自動的に行うために、hookスクリプトを利用します。

#!/bin/sh

DIR=$1

H1="====="
RST_CONTENTS=".. contents:: 目次\n    :local:    \n    :depth: 2 \n"

# reST記法用の目次作成関数
function insert_rst_contents() {
    file_list=`find ./ -name "*.rst"`

    for file in ${file_list[@]}
    do
        # index.rst は処理の対象外
        if [ ${file} = "./index.rst" ];then
            :
        else
            # 既に目次が存在するファイルは対象外
            if grep '.. contents::' ${file}; then
                :
            else
                if grep -E $H1 ${file}; then
                    h1_row_number=`grep -n $H1 ${file} |sed "s/:.*//"|head -1`
                    insert_row=`expr ${h1_row_number} + 1`
                    sed -i -e  "${insert_row}a ${RST_CONTENTS}" ${file}
                fi
            fi
        fi
    done
}

source /usr/local/sphinx/bin/activate

cd ${DIR}/source
# PandocによるreST / Markdown変換処理
find ./ -name "*.md" | sed -e 's/\.md$//' | xargs -i pandoc -f markdown -t rst -o {}.rst {}.md
# tocの挿入
insert_rst_contents
# HTMLビルド
make html

上記のスクリプトを、/usr/local/bin/sphinx_pandoc_make に保存しておきます。(ちなみにこのスクリプトはだいぶゴリ押しです)

そして、プッシュの受入時に実行されるように、プッシュ先のレポジトリのhgrcに以下の通り記載しておきます。

[hooks]
pretxnchangegroup.1 = hg update >&2
pretxnchangegroup.2 = sh /usr/local/bin/sphinx_pandoc_make /var/hg/hoge

/var/hg/hoge の部分は、make html を実行したいディレクトリですので適時読み替えてください。sphinx_pandoc_makeの第一引数として渡ることになります。

ディレクトリ、ファイルが更新された場合に検知をしてビルドする、という仕組みによるビルド自動化方法もちらほら見かけます。悪い方法だとは思いませんが、ビルドの成果物(= 閲覧できるHTML)がレポジトリの状態と一致しないという状態を避けたいと考えたので、ビルドはコミット・プッシュ起点で行われる仕組みを採用しました。

運用ルールは緩めに制定

Markdownは極めてシンプルな記法です。従って、MarkdownでSphinxを利用する場合、コーディングへの制約を設ける必要はほぼないと言えます。むしろ、レポジトリのディレクトリ構成や、どの粒度でSphinx-Projectを作成するかのほうが重要です。

まずディレクトリについてですが、レポジトリを細かく分散させるとWebサーバーの設定との兼ね合いが複雑化することが予想されました。反対に集約しすぎると、プロジェクトとドキュメントの関連性が曖昧になる可能性がありました。そこで、Sphinxのレポジトリ実態は各プロジェクトに紐付け、Web参照領域にはシンボリックリンクで紐付けるという構成を取りました。

ドキュメントだけのプロジェクトの場合

/var/hg/test_document/ /var/www/sphinx/test_document -> /var/hg/test_document/build/html

開発プロジェクトの場合

/var/hg/test_project -- docs -- src /var/www/sphinx/test_project -> /var/hg/test_project/docs/build/html

作成する粒度については正直まだ曖昧で、レポジトリで分けることもあれば単一のレポジトリで管理することも、単一のプロジェクトの中でディレクトリを切って管理することもあります。

この点は、テキストベースのファイルですし、変えたくなったら変えれば良いかな、程度に緩く考えています。MS OFficeのWordベースのドキュメントの場合、複数ファイルのマージや構成の再編は少々骨が折れますが、Sphinxならソースコードのリファクタリングのつもりでやれば、そこまで苦労はしないでしょう。

チームへの浸透の過程

前段として、社内勉強会で@tebonz氏がSphinxを取り上げ、その際にbizstyleというスタイルを紹介してくれました。勉強会もハンズオン的な中身だったので、そのときにチームの中でなんとなく使えるかも、という下地が出来ていたのだと思います。

そこからはまず単一のSphinxプロジェクトを公開して、とにかくドキュメントを増やすことを行いました。そのときに上述したMarkdownの利用や自動ビルド設定などは一通り済んでいました。

Tipsを中心としたライトな内容で書いてるうち、数人が書き始め、、と自然に浸透していったのではないかと振り返っています。

まとめ

  • 成果物の見た目は非常に重要。これだけでモチベーションが上がる。
  • ビルドが自動化されていることも重要
  • テキストベースでドキュメント管理をできることのメリットを明確にし、理解してもらう
  • makeしてHTMLが生成されるというコンパイルチックな行程とエンジニアの親和性を強調する

Markdownを採用したことも浸透を後押しした要因の一つかも知れませんが、reSTの表現力が抑制されてしまっている面もあるため、ある程度トレードオフの関係にあります。従ってMarkdownかreSTか、という部分は As you like. と考えて頂くのが良いかと。

2014年の抱負

SI業務における納品物をどうするかが継続課題です。docxへの変換やPDF化も実証済みですが、主にレイアウト面での兼ね合いで、従来のdocxファイルへの完全代替までには至っていません。

この解決として、SphinxからLaTeXを利用した、納品物水準のPDF作成を2014の目標とします。

また、12月10日、Sphinx 1.2がリリースされましたね!来年は本年以上Sphinx普及にコミットしていきたいと思います!