CIフレンドリなデータベースドキュメント生成コマンド tbls を作った

進捗報告です。

ドキュメントの更新が追いつかない問題を解決したい

活発なプロジェクトでは、システムのソースコードだけにとどまらず、データベース設計やアーキテクチャもどんどん変化していきます。

そういった時、一度作ったドキュメントを追従させていくのは至難の技です。主に優先順位とかモチベーションとかの理由で。

そういった課題を解決すべく、今回はデータベーススキーマのドキュメントを生成するツール tbls を作ってみました。

github.com

これは何?

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で回しています。

github.com

現在ではTravis CIのCRON機能を使っていて、定期的に "Broken" とメールが飛んできます。

f:id:k1LoW:20180521225503p:plain

というわけで

MySQLもさっさと対応して、「データベースのドキュメントがないプロジェクト」「データベースのドキュメントが古いプロジェクト」を撲滅していこうと思います!