LoginSignup
2
1

More than 1 year has passed since last update.

tbls と GitLab CI でデータベースドキュメントを自動生成する

Posted at

データベースドキュメントは、フォーマットを決めたり、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 installartisan 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_repositorywrite_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/*

2
1
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
1