データベースドキュメントは、フォーマットを決めたり、ER図を作ったり、スキーマの変更に合わせて更新が必要だったり面倒なことが多い。そこで tbls と GitLab CI を使って、最新のドキュメントを自動生成できる仕組みを作ってみた。
tblsとは
データベースに接続してMarkdownでスキーマのドキュメントを生成するツール。データベース全体のER図と各テーブルごとのER図も生成してくれる。テンプレートのカスタマイズもできるのでかなり柔軟に対応できる。サンプル
tblsはGo言語で作られたシングルバイナリなのでCI環境でも動かしやすく、ER図の生成は内蔵のGraphvizで行われるため、別途インストールが必要ないのも良い(Go言語のgo-graphvizが使われているらしい)。
tblsはデータベースのリンターにもなり、
- テーブルやカラムにコメントがついているか
- 1テーブルあたりのカラム数
-
created_at
のようなカラムを必須に設定 - 重複したリレーションがないか
- カバレッジの算出
などほかではあまり見ない機能もある。
GitLab CI のジョブを作成する
GitLab CIの説明は割愛。次の処理を行うジョブを作成します。
- データベースを立ち上げる
- マイグレーションを実行
- tlbs でデータベースからドキュメントを生成
- 生成されたドキュメントをコミット・プッシュ
- ジョブはマイグレーションファイルの変更がプッシュされた時のみ実行
作成したジョブは以下の通り。GitLab RunnerはDocker executorを使用しています。
tbls:
stage: document
services:
- mysql:8.0
variables:
MYSQL_DATABASE: database
MYSQL_USER: user
MYSQL_PASSWORD: password
MYSQL_ROOT_PASSWORD: root
script:
- composer install
- cp .env.example .env
- DB_HOST=mysql DB_PASSWORD=root php artisan migrate
- source <(curl https://raw.githubusercontent.com/k1LoW/tbls/main/use)
- tbls doc --rm-dist mysql://root:root@mysql:3306/database
- git config user.name tbls
- git config user.email project***_bot@noreply.example.com
- git remote set-url --push origin https://$CI_PROJECT_NAME:$GITLAB_TOKEN@$CI_SERVER_HOST/$CI_PROJECT_PATH.git
- git add -N .
- git diff --quiet || git commit -am "Update database documents"
- git push origin HEAD:$CI_COMMIT_BRANCH
rules:
- if: $CI_COMMIT_BEFORE_SHA != '0000000000000000000000000000000000000000'
changes:
- .tbls.yml
- database/migrations/*
今回はLaravel/MySQLのプロジェクトでしたが、composer install
~artisan migrate
あたりのコマンドを
各種フレームワークに置き換えて考えてもらえれば問題ないはず。
ジョブを構成するにあたって重要なポイントを簡単に解説しておきます。
GitLab CI で データベースを使う
services
でDockerイメージを指定しておくことで、ジョブの実行中に別のコンテナを立ち上げておくことができます。コンテナの立ち上げ時に必要な環境変数はvariables
で指定します。
services:
- mysql:8.0
variables:
MYSQL_DATABASE: database
MYSQL_USER: user
MYSQL_PASSWORD: password
MYSQL_ROOT_PASSWORD: root
アクセストークンでプッシュ
そのままではリポジトリにPushする権限がないので、Project Access Tokensを準備しました。
ロールはDeveloper
以上、スコープはread_repository
とwrite_repository
にチェックを入れてトークンを作成し、CI変数に設定しておきます。(今回はGITLAB_TOKEN
という名前で設定しています)
設定したトークンを使ってリモートURLをgit remote set-url
コマンドで認証付きのものに変更します。
- git config user.name tbls
- git config user.email project***_bot@noreply.example.com
- git remote set-url --push origin https://$CI_PROJECT_NAME:$GITLAB_TOKEN@$CI_SERVER_HOST/$CI_PROJECT_PATH.git
差分があるときだけコミット
基本的にはスキーマに変更があるときにしかジョブは実行されませんが、生成されたドキュメントに変更がなかった場合の対策をしておきます。
git diff
で新規ファイルを含んだ差分を表示するため、事前にgit add -N .
を実行します。
git diff
は--quiet
をつけておくことでexit codeで差分の有無を表してくれるので、差分がある場合のみgit commit -am
を実行します。
- git add -N .
- git diff --quiet || git commit -am "Update database documents"
- git push origin HEAD:$CI_COMMIT_BRANCH
マイグレーションファイルが変更された場合のみジョブを実行する
ファイルの変更を検出し実行するには、rules:changes
にファイルパスを記載します。
スケジュールパイプラインや手動パイプラインなどではrules:changes
は常にtrue
と評価されるので、if
の指定も必要になります。(今回は新規ブランチをプッシュした際にジョブが実行されてしまうのが嫌だったので$CI_COMMIT_BEFORE_SHA
を条件に設定してます)
rules:
- if: $CI_COMMIT_BEFORE_SHA != '0000000000000000000000000000000000000000'
changes:
- .tbls.yml
- database/migrations/*