DB設計書の更新を自動化してみた

## 1. はじめに

業務ではDB設計書をエクセルで記載することが多いのですが、ドキュメントが更新されずに実装と異なることを課題に感じていました。DB設計に使用できるツールを探しているときに`dbdocs`というツールを見つけました。
`dbdocs`ではCLIが用意されているため、GitHub Actionsで自動化できると考えました。この記事ではDB設計書を`dbdocs`で作成し、GitHub Actionsを使って自動更新する手順を紹介したいと思います。
## 2. 対象読者

- DB設計ツールを探している方
- 実装と乖離しないDB設計書を模索している方
- Laravelを使っている方

## 3. 目次
- [1. はじめに](#1-はじめに)
- [2. 対象読者](#2-対象読者)
- [3. 目次](#3-目次)
- [4. dbdocsについて](#4-dbdocsについて)
- [5. 環境](#5-環境)
- [6. 手順](#6-手順)
  - [6-1. DBMLの出力](#6-1-dbmlの出力)
  - [6-2. dbdocsの初期設定](#6-2-dbdocsの初期設定)
  - [6-3.dbdocsのトークン発行](#6-3dbdocsのトークン発行)
  - [6-4. GitHub Actionsのyamlファイル作成](#6-4-github-actionsのyamlファイル作成)
- [7. さいごに](#7-さいごに)
- [8. 参考サイト](#8-参考サイト)

## 4. dbdocsについて

https://dbdocs.io/

`dbdocs`ではDBMLを使用してスキーマを定義します。定義したDBMLからWebベースのドキュメントを作成することができます。基本的な機能は無料で使うことができます。詳細についてはリンクからご確認ください！

`dbdocs`では[デモサイト](https://dbdocs.io/Holistics/Ecommerce)が用意されていますので、是非触ってみてください！
画像はデモサイトのキャプチャです。

![cap2023_11_27_23_58_46_994.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584089/9a93c626-49e2-52a5-b8b2-8fcf22115b37.png)
![cap2023_11_27_23_59_9_812.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584089/4f4fd0e0-f790-d5dd-654e-5e929969d631.png)




## 5. 環境

本記事ではLaravelプロジェクトを前提にしています。
`composer.json`及び`package.json`です。各ファイルの一部は省略しています。

```composer.json


{
    "require": {
        "php": "^8.1",
        "guzzlehttp/guzzle": "^7.2",
        "laravel/framework": "^10.10",
        "laravel/sanctum": "^3.3",
        "laravel/tinker": "^2.8"
    },
    "require-dev": {
        "aphisitworachorch/kacher": "dev-master",
        "fakerphp/faker": "^1.9.1",
        "laravel/pint": "^1.0",
        "laravel/sail": "^1.18",
        "mockery/mockery": "^1.4.4",
        "nunomaduro/collision": "^7.0",
        "phpunit/phpunit": "^10.1",
        "spatie/laravel-ignition": "^2.0"
    },
}
```

```package.json
{
    "devDependencies": {
        "axios": "^1.1.2",
        "laravel-vite-plugin": "^0.8.0",
        "vite": "^4.0.0"
    },
    "dependencies": {
        "dbdocs": "^0.8.4"
    }
}

```

## 6. 手順

### 6-1. DBMLの出力

まずは`dbdocs`で使用するためのDBMLファイルを生成します。
ここでは[aphisitworachorch/kacher](https://github.com/aphisitworachorch/kacher)を使って出力します。

```bash
$ composer require --dev aphisitworachorch/kacher:dev-master
$ php artisan dbml:parse
```

コマンド実行により`storage/app/dbml`直下にDBMLファイルが出力されます。
(出力内容はDBML形式であるがファイルの拡張子は`.txt`になっています)


### 6-2. dbdocsの初期設定

次に、出力したDBMLファイルを使って`dbdocs`の初期設定を行います。
手順は公式サイトの[ドキュメント](https://dbdocs.io/docs)に沿って進めます。

```bash
$ npm install dbdocs
$ npx dbdocs login
# 入力したメールアドレスへOPTコードが送信されるので、コードを入力する

$ npx dbdocs build <DBMLファイルのパス> --project=<プロジェクト名>
# プロジェクト名は任意の名前で大丈夫です
```

最後のコマンドが成功すると、生成されたdbdocsプロジェクトのURLが表示されます。
そのURLにアクセスするとDBMLファイルに基づいたドキュメントが生成されていることが確認できます。

`dbdocs`の無料プランではURLが公開されているため、パスワードを設定することを推奨します。
```bash
$ npx dbdocs password --set <パスワード> --project <プロジェクト名>
```

### 6-3.dbdocsのトークン発行

`dbdocs`のトークンを使用することでメールアドレスによるログインなしに更新することができます。トークンの発行は下記のコマンドを実行します。

```bash
$ dbdocs token -g
```

発行されたトークンはLaravelプロジェクト直下の`.env`ファイルに下記の環境変数で定義します。

```
DBDOCS_TOKEN=<発行されたトークン>
```

### 6-4. GitHub Actionsのyamlファイル作成

最後に、GitHub Actionsのyamlを作成します。
下記は`database/migration`以下が更新されると`dbdocs`を更新する例です。
コード内容の解説は割愛しますが、`dbdocs`周りはコメントで補足しています。

```yaml
name: dbdocs CI

on:
  push:
    branches:
      - main
    paths:
      - "database/migrations/**"

jobs:
  setup:
    runs-on: ubuntu-latest

    services:
      db:
        image: mysql:8.0
        ports:
          - 3306:3306
        env:
          MYSQL_ROOT_PASSWORD: root
          MYSQL_DATABASE: dbdocs
    env:
      DB_CONNECTION: mysql
      DB_HOST: 127.0.0.1
      DB_PORT: 3306
      DB_DATABASE: dbdocs
      DB_USERNAME: root
      DB_PASSWORD: root

    steps:
      - uses: actions/checkout@v2
      - name: cache vendor
        id: cache
        uses: actions/cache@v1
        with:
          path: ./vendor
          key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
          restore-keys: |
            ${{ runner.os }}-composer-

      - name: copy .env.example
        run: cp .env.example .env
      - name: composer install
        if: steps.cache.outputs.cache-hit != 'true'
        run: composer install -n --prefer-dist
      - name: migrate
        run: php artisan migrate

        # dbdocsのCLIパッケージをインストールします
      - name: install dbdocs
        run: npm install -g dbdocs
        # 正常にパッケージがインストールできたか確認します
      - name: Check dbdocs
        run: dbdocs
        # dbmlファイルを生成します。
      - name: create dbml file
        run: php artisan dbml:parse
        # 生成されたファイル名は毎回異なるため、dbdocs.dbmlというファイル名にリネームします
      - name: rename dbml file
        run:  mv storage/app/dbml/`ls storage/app/dbml/` storage/app/dbml/dbdocs.dbml
        # 生成されたdbmlファイルでdbdocsを更新します
      - name: update dbdocs
        run: dbdocs build ./storage/app/dbml/dbdocs.dbml --project=<プロジェクト名>
```

このCIにより、Laravelプロジェクトでmigrationファイルが更新されるたびに`dbdocs`が自動更新されて、ドキュメントと実装が乖離する課題を解決することができます！

## 7. さいごに

`dbdocs`は無料プランでも十分使えると思っています！
有料プランに入るとテーブルをグループ化したり、テーブルヘッダー色を変更できたり、ドキュメントとしての見やすさは向上するかと思います。しかし、有料プランの月60ドルは辛いので現状入る予定はないかなと思っています。有料プランの機能が増えたら、課金も検討したいと思います！

## 8. 参考サイト

- [dbdocs](https://dbdocs.io/)
- [aphisitworachorch/kacher](https://github.com/aphisitworachorch/kacher)