LoginSignup
2
2

More than 5 years have passed since last update.

ドキュメントがメンテナンスされない問題に立ち向かう with Sphinx

Last updated at Posted at 2019-01-19

ドキュメント管理はサービスの運用に頭を悩ませる課題の一つです。
常に最新の状態を保ち、記載内容には誤りがない...
当然のように聞こえますが、
それを実現するのは非常に難しいという事は敢えて言うまでもないことでしょう。

とはいえ、"ドキュメントは管理されないものだから仕方がない"と割り切ってしまうわけにもいきません。
今回はドキュメントがメンテナンスされるような仕組みを構築する事で
この問題に立ち向かう方法を紹介します。

ドキュメントを継続的にメンテナンスするために必要な要素
メンテナンスされやすい環境を構築するにあたり 前提となる幾つかの項目を挙げました。
今回は これらの条件を満たす環境の構築を目指します。

  • ソースコードとドキュメントの一元管理
  • ドキュメントの更新に対するレビュー
  • バージョン管理
  • かっこいい見た目 ← 重要

具体的にどう実現するか

image.png

今回はsphinxと呼ばれるPython製のドキュメント生成ツールを利用します。

Sphinxの特徴

  • reStructuredText記法で書かれたテキストファイルからHTML, PDF等を生成。
  • レイアウトテンプレートで綺麗なドキュメントが作成可能。
  • Markdownにも対応

実際のsphinxを使って出来たドキュメントのイメージ
image.png

このSphinxで生成したHTMLを公開する場所については GitHub Pageを利用します。

GitHub Pageの特徴
GitHubの提供する静的サイトのホスティングサービス。
master branchのdocsディレクトリ直下にHTMLを置くか
gh-branchs branchの直下にHTMLを置くことで静的サイトを公開することが出来ます。

今回は、master branchに生成されたHTMLファイルを置きたくないので
gh-branchsを使った公開を採用します。

ただ、ドキュメントの更新のたびにgh-branchにpushするのは面倒なので、
master branchに更新がかかったタイミングでCI経由でgh-branchに自動でpushできるようにCI用のシェルを用意します。

説明しないこと

sphinxの書き方は非常に長くなるため、ここでは解説しません。
書き方が知りたい方はSphinx日本ユーザ会が提供してくれているドキュメントを参考にして下さい。

実践

※ 今回の内容で作成したプロジェクトはこちらに上げています。
https://github.com/ohs30359-nobuhara/sphinx-gh-page

サンプルアプリの作成

ドキュメントだけ作っても良いのですが、
実際に運用するケースを想定して簡単なアプリを用意します。

本題ではないので expressを使った簡単なものです。

$ npm i express

殆どサンプルそのままです。

var express = require("express");
var app = express();

var server = app.listen(3000, function(){
    console.log("Node.js is listening to PORT:" + server.address().port);
});

app.get("/", function(req, res, next){
    res.send('Sphinx!!');
});

Sphinxの導入

アプリが出来たところで本題であるsphinxを導入していきます。
sphinxはpipで導入するため pythonをインストールします。

$ brew install python
$ which pip
> /usr/local/bin/pip

続いてpipでSphinxをインストール。

$ pip install -U Sphinx

これで準備は完了です。

ドキュメントの作成

まずはドキュメントを管理するためのdocディレクトリを用意します。

$ mkdir doc

続いてdocディレクトリに移動して以下のコマンドを実行します。

$ sphinx-quickstart

色々聞かれますが、基本すべてyesで問題ありません。
sphinx-quickstartによりdoc配下にドキュメントのリソースが作成されます。

.
├── Makefile
├── make.bat
└── source
    ├── conf.py
    └── index.rst

この状態で $ make htmlを実行するとdoc/build配下にドキュメントが作成されます。

$ make html

作成されたドキュメントを表示してみます。

image.png

Themeで見栄えを整える

流石に味気が無さすぎるので見栄えを整えます。
sphinxにはThemeと呼ばれるデザインテンプレートが用意されているので、それを利用します。

pipでTeemaを取得してきます。

$ pip install sphinx_rtd_theme

続いて doc/source/conf.pyに以下を追記します。

doc/source/conf.py
import sphinx_rtd_theme
html_theme = "sphinx_rtd_theme"
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]

この状態で もう一度make htmlを実行します。

$ make html

もう一度 ドキュメントを表示すると今度は設定したTeemaが適用されいるはずです。
image.png

Markdownを使えるようにする

これでドキュメントを書いていく準備は出来ましたが
sphinxはrst形式で書かないといけないため慣れていない人からすれば面倒です。

新しく覚えるの面倒だしMarkdownでも書きたいという要望は発生すると思うので
Markdownでドキュメントを書けるようにします。

pipでcommonmark, recommonmarkを取ってきます。

$ pip install commonmark recommonmark

先程と同じく doc/source/conf.pyを編集します。

src/doc/source/conf.py
source_suffix = ['.rst', '.md']
from recommonmark.parser import CommonMarkParser

source_parsers = {
    '.md': CommonMarkParser,
}
from recommonmark.transform import AutoStructify

github_doc_root = 'https://github.com/rtfd/recommonmark/tree/master/doc/'
def setup(app):
    app.add_config_value('recommonmark_config', {
            'url_resolver': lambda url: github_doc_root + url,
            'auto_toc_tree_section': 'Contents',
            }, True)
    app.add_transform(AutoStructify)

これで準備は完了です。
早速、Markdownでページを追加してみます。

まずはsampleディレクトリを作成。

$ mkdir ./doc/sample

とりあえずタイトルだけの簡単なページを作成します。

doc/sample/index.md
# SAMPLE INDEX

続いてdoc/source/index.rst に先ほど作成したファイルへのリンクを追記します。

doc/source/index.rst
   :maxdepth: 2
   :caption: Contents:

   /sample/index

これでMarkdown対応は完了です。
$ make htmlを実行するとページが追加されていることが確認できます。

GitHub Pageに公開する

ドキュメントが作成できるようになったので GitHub Pageに公開します。
基本的に自動生成されるbuild配下のファイル群は管理したくないため
master branchではdoc/sourceのみを管理させるようにし、
gh-pages branchに公開対象のhtmlを管理させるようにします。

最終的なディレクトリ構成は以下になります。
( gh-pages branch は build配下のファイルをそのまま持ってきています )

# master branch
.
├── app.js
├── ci
│   └── genDoc.sh
├── doc
│   ├── Makefile
│   ├── make.bat
│   └── source
│       ├── conf.py
│       ├── index.rst
│       └── sample
│           └── index.md
├── package-lock.json
└── package.json

# gh-pages branch
.
├── _sources
├── _static
├── genindex.html
├── index.html
├── objects.inv
├── sample
├── search.html
└── searchindex.js

まずci用ディレクトリを作成し、シェルを用意します。

ci/genDoc.sh
# move to this file
cd `dirname $0`

# move project root & remove files 
cd ..
git checkout gh-pages
find ./ | grep -v .git | xargs rm -r

# get resources from master branch 
git checkout master doc

# build  doc
cd ./doc
make html

# move builded file 
cd ../
mv ./doc/build/html/* ./

# deploy
rm -rf ./doc
touch .nojekyll
git add -A
git commit -m 'updating doc'
git push origin gh-pages

# back to master branch
git checkout master

順番に解説していきます。

cd `dirname $0 でシェルが置かれているpathに移動します。

# move to this file
cd `dirname $0`

続いてプロジェクトルートに戻り gh-pages branchにチェックアウト。
find ./ | grep -v .git | xargs rm -rで git系以外のファイルをすべて削除。

cd ..
git checkout gh-pages
find ./ | grep -v .git | xargs rm -r

master branchからdocディレクトリだけをチェックアウトして
make htmlでドキュメントを作成

# get resources from master branch 
git checkout master doc

# build  doc
cd ./doc
make html

プロジェクトルートに戻り、buildされたhtmlをプロジェクトルートに移動。

# move builded file 
cd ../
mv ./doc/build/html/* ./

docディレクトリは不要なので削除。

GitHub Pagesでホスティングされたファイルは、Jekyllによって処理されてしまうので
.nojekyllファイルを追加してJekyしてをkill。

htmlファイルと.nojekyllをcommit, pushしてmaster branchに戻る。

# deploy
rm -rf ./doc
touch .nojekyll
git add -A
git commit -m 'updating doc'
git push origin gh-pages

git checkout master

これでgh-pagesにドキュメントが公開されているはずです。
gh-pagesへのURLはGitHubのsettingに表示されています。

image.png

後は 現在利用しているCIで先程のシェルを実行するようにすれば
ドキュメントの更新をCIにより自動化することが出来ます。

運用する

これで最低限CIでドキュメントをデプロイする準備が整いました。
最終的には人が更新するものなので正しくメンテナンスされるように
ドキュメントを更新するタイミングや書き方の規約をプロジェクトで設定して下さい。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2