ドキュメント管理はサービスの運用に頭を悩ませる課題の一つです。
常に最新の状態を保ち、記載内容には誤りがない...
当然のように聞こえますが、
それを実現するのは非常に難しいという事は敢えて言うまでもないことでしょう。
とはいえ、"ドキュメントは管理されないものだから仕方がない"と割り切ってしまうわけにもいきません。
今回はドキュメントがメンテナンスされるような仕組みを構築する事で
この問題に立ち向かう方法を紹介します。
ドキュメントを継続的にメンテナンスするために必要な要素
メンテナンスされやすい環境を構築するにあたり 前提となる幾つかの項目を挙げました。
今回は これらの条件を満たす環境の構築を目指します。
- ソースコードとドキュメントの一元管理
- ドキュメントの更新に対するレビュー
- バージョン管理
- かっこいい見た目 ← 重要
具体的にどう実現するか
今回はsphinxと呼ばれるPython製のドキュメント生成ツールを利用します。
Sphinxの特徴
- reStructuredText記法で書かれたテキストファイルからHTML, PDF等を生成。
- レイアウトテンプレートで綺麗なドキュメントが作成可能。
- Markdownにも対応
この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
作成されたドキュメントを表示してみます。
Themeで見栄えを整える
流石に味気が無さすぎるので見栄えを整えます。
sphinxにはThemeと呼ばれるデザインテンプレートが用意されているので、それを利用します。
pipでTeemaを取得してきます。
$ pip install sphinx_rtd_theme
続いて 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が適用されいるはずです。
Markdownを使えるようにする
これでドキュメントを書いていく準備は出来ましたが
sphinxはrst形式で書かないといけないため慣れていない人からすれば面倒です。
新しく覚えるの面倒だしMarkdownでも書きたいという要望は発生すると思うので
Markdownでドキュメントを書けるようにします。
pipでcommonmark, recommonmarkを取ってきます。
$ pip install commonmark recommonmark
先程と同じく 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
とりあえずタイトルだけの簡単なページを作成します。
# SAMPLE INDEX
続いて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用ディレクトリを作成し、シェルを用意します。
# 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に表示されています。
後は 現在利用しているCIで先程のシェルを実行するようにすれば
ドキュメントの更新をCIにより自動化することが出来ます。
運用する
これで最低限CIでドキュメントをデプロイする準備が整いました。
最終的には人が更新するものなので正しくメンテナンスされるように
ドキュメントを更新するタイミングや書き方の規約をプロジェクトで設定して下さい。