tblsを使ってデータベースドキュメントを作成しよう! [GithubActionsで自動生成もさせてみる]

# tblsとは？
tblsとは、データベースドキュメントを自動生成することのできるツールです。

データベースのスキーマ、テーブル作成クエリ、ER図を生成してくれます。

https://github.com/k1LoW/tbls

# tblsを使うメリット
共同開発において、ドキュメントをプロジェクト内において共有することができます。

ドキュメントを書くメリットとしては、`コードを見なくても表や文語で情報を伝達できる`だと思っています。
これによって以下の効果が出ると思います。
- 新規メンバーのキャッチアップがスムーズになる
- トラブルシューティングが楽になる
- 別領域(フロントエンド）の人でも理解がしやすくなる

があると思います。

ドキュメントの作成は手間がかかるのですが、tblsを使えば自動でドキュメントを統一した形式で出してくれるのでとても少ないコストで使用することができます。また、データベースに入らずテーブルのカラムの情報を出してくれるので非常に便利です。

# インストール

tblsは、go製のCLIツールなのでGOPATHを繋ぐことで`go install`コマンドを使ってインストールできます。

```zsh:go
go install github.com/k1LoW/tbls@latest
```

homebrewでもインストール可能です。
```zsh:zsh
brew install k1LoW/tap/tbls
```

# tblsを使ってみる

設定ファイルとなる`.tbls.yml`をルートに作成して以下のように記述します。

```.tbls.yml
# .tbls.yml

# DSN (Database Source Name) to connect database
dsn: mysql://root:root@127.0.0.1:3306/db
# Path to generate document
# Default is `dbdoc`
docPath: docs/schema
```

下のコマンドでドキュメントを生成できます。
```zsh:zsh
tbls doc
```

そうすると下のようなファイルが生成されます。
```zsh:zsh
.
├── README.md
├── schema.json
├── schema.svg
├── todos.md
└── todos.svg
```

READMEにはテーブルの詳細情報とER図が写し出されます。

![スクリーンショット 2024-11-14 0.02.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3766230/8e0fc6a9-219d-5654-a619-99a3bbfe8a84.png)

>今回テーブルが一つしかないため分かりづらく申し訳ないです。

todo.mdには下のようにテーブル作成のクエリやカラムの情報など、todoテーブルに関する情報が載せられています。
![スクリーンショット 2024-11-14 0.06.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3766230/1277915d-496d-acd2-5535-45720b549e28.png)


# ドキュメントを上書きしたいとき
ドキュメントの上書きは`tbls doc`コマンドでは行えません。

```zsh:zsh
❯ tbls doc
output files already exists
```

上書きする場合は下のコマンドを使用します。

```zsh:zsh
tbls doc --rm-dist
```

# 設定ファイルを指定したいとき

設定ファイルである`.tbls.yml`のファイルパスを--config(-c)で指定します。

```zsh:zsh
tbls doc --config "./config/.tbls.yml"
```

# jsonとsvgを削除してスッキリさせたい

先ほど生成したファイルはjsonやsvgなどファイルが多くて少しスッキリさせたいですよね。

そのためにjsonを出力させず、スキーマを描くために使っていたsvgの代わりにmermaidを使用したいと思います。

:::note
### mermaidとは
markdownで図形やUMLを書くことができるダイアグラムツールです。
:::

先ほどの`.tbls.yml`を下のように変更します。

```.tbls.yml
# .tbls.yml

# DSN (Database Source Name) to connect database
dsn: mysql://root:root@127.0.0.1:3306/db
# Path to generate document
# Default is `dbdoc`
docPath: docs/schema

disableOutputSchema: true

er:
  format: mermaid
```

`disableOutputSchema`で`schema.json`を出力させないようにしています。

`format:mermaid`でマーメイドを出力させるようにしています。

![スクリーンショット 2024-11-14 0.26.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3766230/13e9c363-a58a-1934-9e5d-db079ba8baae.png)

# GithubActionsで自動生成

pushをトリガーとして、tblsを用いたドキュメント自動生成をやってみようと思います。

`./.github/workflows/tbls.yml`に下のようなファイルを書いてみました。

```./.github/workflows/tbls.yml
name: tbls-gen

on: push

jobs:
  gen:
    name: tbls-gen
    permissions:
      contents: write
    runs-on: ubuntu-latest
    timeout-minutes: 10
    services:
      mysql:
        image: mysql:8.0
        ports:
          - 3306:3306
        env:
          MYSQL_ALLOW_EMPTY_PASSWORD: yes
          MYSQL_DATABASE: root
    steps:
      - name: checkout
        uses: actions/checkout@v4.2.2
      - name: Set up Go
        uses: actions/setup-go@v5.1.0
        with:
            go-version-file: 'go.mod'
            cache: false
            check-latest: true
        id: go
      - name: mod tidy
        run: go mod tidy
      - name: install sql-migrate
        run: go install -v github.com/rubenv/sql-migrate/sql-migrate@latest
      - name: mysql wakeup
        run: |
          until (echo 'SELECT 1' | mysql -h 127.0.0.1 -P 3306 -uroot --silent &> /dev/null); do echo "waiting for mysql to be connectable" && sleep 2; done
      - name: mysql migrate for tbls
        run: |
          mysql -h 127.0.0.1 -P 3306 -u root -e "CREATE DATABASE IF NOT EXISTS db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_bin"
          sql-migrate up -env="ci"
      - name: install tbls
        uses: k1low/setup-tbls@v1
      - name: run tbls
        run: |
          TBLS_DSN=mysql://root:@localhost:3306/db tbls doc --rm-dist --config .tbls.yml
      - name: push tbls doc
        run: |
          git config user.name github-actions[bot]
          git config user.email github-actions[bot]@users.noreply.github.com
          git add .
          git commit -m "[ci skip] generate database document"
          git push origin HEAD
```

実際にpushするとCIが回り始めます。

![スクリーンショット 2024-11-15 14.28.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3766230/924fbb4e-a4c0-8bcd-e54b-446d6a9931fe.png)


## ymlに関する説明
`on:`でトリガーを設定しています。今回はpushにしています。
```yml
on: push
```

`jobs`の配下にCIで行う内容を決めていきます。
`gen:`はjobのカテゴリとして設定しています。
```yml
jobs:
  gen:
```

`name`でjobに名前をつけます。
```yml
name: tbls-gen
```

`permissions`は外部のbotとかに権限を付与できます。
```yml
permissions:
      contents: write
```

`runs-on`はjobを実行するホストマシン(OS)を決定できます。今回はUbuntuにしています。
```yml
runs-on: ubuntu-latest  
```

`timeout-minutes`でjobsのタイムアウトするまでの制限時間を10分としています。

```yml
timeout-minutes: 10
```

`services`でdockerのimageを持ってきています。こうすることでtblsの生成に必要なmysqlを立てることができます。

```yml
services:
      mysql:
        image: mysql:8.0
        ports:
          - 3306:3306
        env:
          MYSQL_ALLOW_EMPTY_PASSWORD: yes
          MYSQL_DATABASE: root
```

`steps`では、jobで行う一連の処理を記述しています。

|各step|処理|
|---|---
|checkout|リポジトリをクローン
|Set up Go|Goを動かす環境をセットアップ
|mod tidy|goの依存関係の整理
|install sql-migrate|sql-migrateを整理
|mysql wakeup|mysqlの立ち上げを行う
|mysql migrate for tbls|マイグレーションを行う
|install tbls|tblsをgithubactionsにインストール
|run tbls|tblsを走らせる
|push tblsdoc|tblsで生成したドキュメントをHEADにpushする

`checkout`では、リポジトリをActions内にクローンしています。
https://github.com/actions/checkout
```yml
 - name: checkout
   uses: actions/checkout@v4.2.2
```

`Set up Go`では、Goの環境をActions内にセットアップしています。

https://github.com/actions/setup-go
```yml
- name: Set up Go
  uses: actions/setup-go@v5.1.0
  with:
    go-version-file: 'go.mod'
    cache: false
    check-latest: true
```

`mod tidy`では、go modの依存関係の整理を行なっています。

```yml
- name: mod tidy
  run: go mod tidy
```

`install sql-migrate`では、goのマイグレーションツールをインストールしています。
```yml
- name: install sql-migrate
  run: go install -v github.com/rubenv/sql-migrate/sql-migrate@latest
```

`mysql wakeup`ではmysqlの立ち上げを行っています。

`SELECT 1`をパイプ(|)でmysqlコマンドに渡して、mysqlが立ち上がったら`SELECT 1`が実行されて終了コード0が返されるので、それで立ち上がったどうかを判断します。
実際に下のように返されます。
```zsh:zsh
shell: /usr/bin/bash -e {0}
```

`--silent`は表示する際の枠線を消すサイレントモードというオプションです。

`&> /dev/null`は標準出力とエラー出力を破棄します。

`do ... done`のところは`until`の条件を満たす場合に"waiting for mysql to be connectable"と表示して、2秒間おきにwhileを実行させます。

```yml
- name: mysql wakeup
run: |
    until (echo 'SELECT 1' | mysql -h 127.0.0.1 -P 3306 -uroot --silent &> /dev/null); do echo "waiting for mysql to be connectable" && sleep 2; done
```

`mysql migrate for tbls`では、マイグレーションを行って、tblsがdbの中に入れるような環境をactions内で作成します。
`mysql-client`の接続コマンドを使って、-e(executeオプション)を使って、データベース作成クエリを実行しています。
```yml
- name: mysql migrate for tbls
  run: |
    mysql -h 127.0.0.1 -P 3306 -u root -e "CREATE DATABASE IF NOT EXISTS db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_bin"
    sql-migrate up -env="ci"
```

`install tbls`では、tblsをactions内でインストールしています。

https://github.com/k1LoW/setup-tbls

```yml
- name: install tbls
  uses: k1low/setup-tbls@v1
```

`run tbls`では、tblsを走らせています。
```yml
- name: run tbls
  run: |
    TBLS_DSN=mysql://root:@localhost:3306/db tbls doc --rm-dist --config .tbls.yml
```

`push tblsdoc`で現在のブランチに変更をコミットとpushを行っています。

```yml
- name: push tbls doc
  run: |
    git config user.name github-actions[bot]
    git config user.email github-actions[bot]@users.noreply.github.com
    git add .
    git commit -m "[ci skip] generate database document"
    git push origin HEAD
```

>actionsが行った変更のコードに対してCIが回らないので注意です



これを使用してぜひ共同開発でのドキュメント共有を行なってください！