進捗報告です。
https://t.co/sVmTUw6klC とりあえずPostgreSQLの実装はできたので、明日からテーブル設計のドキュメント化とそのドキュメントのCIは回せそう
— k1LoW (@k1LoW) 2018年5月20日
ドキュメントの更新が追いつかない問題を解決したい
活発なプロジェクトでは、システムのソースコードだけにとどまらず、データベース設計やアーキテクチャもどんどん変化していきます。
そういった時、一度作ったドキュメントを追従させていくのは至難の技です。主に優先順位とかモチベーションとかの理由で。
そういった課題を解決すべく、今回はデータベーススキーマのドキュメントを生成するツール tbls
を作ってみました。
これは何?
tbls
は対象のデータベースに接続してGitHub FriendlyなMarkdownでスキーマのドキュメントを生成するツールです。
主にGitHubにドキュメントごとコミットされることを想定しており、GFMフォーマットなだけでなく、エントリページが README.md
であることも特徴です。
使い方
ドキュメントの生成
tbls doc
で対象ディレクトリに一気にMarkdownフォーマットでデータベースのドキュメントを生成します。
$ tbls doc postgres://user:pass@hostname:5432/dbname ./dbdoc
既に存在する場合は --force
オプションを利用して上書き可能です。
たったこれだけでこのようなドキュメントが生成されます。
これだけで随分ドキュメント運用が楽になります。
CIとの連携
個人的にはコレがこのツールの特徴だと思っている(そしてもっと改善していきたいところ)のですが、tbls
にはCIと連携することを想定したコマンドがあります。
先ほども書いたように、活発なプロジェクトに対してのドキュメントの追従は課題です。
ドキュメントを生成するコマンドを作っても、そのコマンドを打たなかったら結局は実際のデータベースと離れていきます。
それを解決するためにCIに組み込むコマンドとして tbls diff
を用意しました。
これは対象データベースと既に作られたドキュメントのdiffを出力します。
$ tbls diff postgres://user:pass@hostname:5432/dbname ./dbdoc
たったコレだけをするコマンドですが、(Go製であるがゆえの)シングルバイナリであることからCIとの連携が非常にしやすくなっています。
例えば .travis.yml
に組み込むとしたらこんな感じでしょう。
script: - DIFF=`tbls diff postgres://user:pass@localhost:5432/testdb?sslmode=disable ./dbdoc` && if [ ! -z "$DIFF" ]; then echo "document does not match database." >&2 ; tbls diff postgres://user:pass@localhost:5432/testdb?sslmode=disable ./dbdoc; exit 1; fi
Makefileにコマンドとして組み込むとしたらこんな感じでしょうか。
doc: ## Document database schema tbls doc postgres://user:pass@localhost:5432/testdb?sslmode=disable ./dbdoc testdoc: ## Test database schema document $(eval DIFF := $(shell tbls diff postgres://user:pass@localhost:5432/testdb?sslmode=disable ./dbdoc)) @test -z "$(DIFF)" || (echo "document does not match database." && tbls diff postgres://user:pass@localhost:5432/testdb?sslmode=disable ./dbdoc && exit 1)
テストでは大抵データベースのマイグレーションも走っていると思います。そのテスト環境とうまく連携すればドキュメントが更新されているかどうかもテストすることができます。
サポートデータベース
現時点では残念ながらPostgreSQLのみですが、MySQLも近いうちにサポート予定です。
これでデータベースのドキュメントが本番と違うということはなくなるはず。
ドキュメントの更新をCIでチェックさせるというアイデア
これは余談なのですが、「ドキュメントの更新をCIでチェックさせる」というのはawspecのメンテナンスを続けるうえで得たアイデアです。
awspecのテスト対象はあのAWSです。物凄い勢いで機能が追加されています。そういった意味でawspecはメタ的な作り方をしており、実は、AWSによる新パラメータの追加・削除と共にawspecは勝手に対応していきます。
ただ、その機能ドキュメントを追従させるのが難しかったのでそのためのドキュメント生成をコマンド化し、そしてCIで回しています。
現在ではTravis CIのCRON機能を使っていて、定期的に "Broken" とメールが飛んできます。
というわけで
MySQLもさっさと対応して、「データベースのドキュメントがないプロジェクト」「データベースのドキュメントが古いプロジェクト」を撲滅していこうと思います!