GitHub ActionsでSchemaSpyのER図を生成してGitHubPagesにデータベースのドキュメントをデプロイできるようにしたメモ

# 概要
データベースのドキュメントをSchemaSpyで自動生成してGithubPagesに公開する手順のメモ。
マイグレーションにはdrizzleを使用する。

[公開したドキュメント](https://hibohiboo.github.io/odyssage/odyssage-dbdoc/odyssage/)

[この時点のソースコード](https://github.com/hibohiboo/odyssage/blob/78834487e0b73e2adafa0e10687ea78f3b778cc3/docs/dbdoc/docker-compose.yml)

# 選定
ChatGPTに聞いてみたら下記が候補に挙がった。

| ツール名 | 言語/環境 | 出力形式 | ER 図 | CI/CD 連携 | 主な特徴 |
| --- | --- | --- | --- | --- | --- |
| **tbls** | Go | ~~HTML~~, Markdown, JSON, Dot | ✔️ | ✔️ GitHub Actions, GitLab CI/CD | DB 解析 & ドキュメント自動生成, 設定ファイルでカスタマイズ可 |
| **SchemaSpy** | Java | HTML | ✔️ | ✔️ Jenkins, GitHub Actions | JDBC 経由で DB 接続し詳細な HTML ドキュメントを生成 |
| **dbdocs** | Web | Markdown, HTML | ✔️ | ✔️ (API 経由で可能) | SQL ファイル or Markdown からドキュメントを生成, GUI あり |
| **dbdiagram.io** | Web | PNG, SVG | ✔️ | ❌（手動でエクスポート） | ER 図作成に特化, GUI で視覚的に編集可能 |
| **DBeaver** | Java | HTML, PDF | ✔️ | ❌（手動エクスポート） | DB 管理ツール, スキーマのエクスポート機能あり |

[tbls](https://github.com/k1LoW/tbls)は次のような[マークダウン](https://github.com/hibohiboo/odyssage/tree/78834487e0b73e2adafa0e10687ea78f3b778cc3/infra/local/neon/dbdoc)を生成できたが、HTMLは出力できないようだった。上記の表の信用度が下がった。

また、公式ドキュメントではＳＶＧのER図を作成できるとあったが、`Segmentation Fault (SIGSEGV)` のエラーをだして失敗してしまった。
上記のマークダウンは`--without-er`をつけて生成したものである。

つぎに、[SchemaSpy](https://github.com/schemaspy/schemaspy)を試してみた。最終更新が2023と、活発でないのが不安。安定していると思えばいいのかな。

# ソースコード
[GitHub ActionsでSchemaSpyのER図を生成してS3にアップロードする](https://zenn.dev/shuhei_takada/articles/ecb030e6529fee)を参考にした。

```Dockerfile:docs/dbdoc/schemaspy/Dockerfile.dev
FROM openjdk:11-jdk

RUN apt-get update && apt-get install -y fontconfig fonts-dejavu && \
    wget -O schemaspy.jar https://github.com/schemaspy/schemaspy/releases/download/v6.2.4/schemaspy-6.2.4.jar && \
    wget -O /postgresql.jar https://jdbc.postgresql.org/download/postgresql-42.7.3.jar && \
    rm -rf /var/lib/apt/lists/*
```

```properties:docs/dbdoc/schemaspy/schemaspy.properties
# データベースのタイプをpgsqlで指定
schemaspy.t=pgsql
# schemaspyのコンテナ内でのJDBCドライバのパス
schemaspy.dp=/postgresql.jar
# データベースのプロパティ
schemaspy.host=localhost
schemaspy.port=5432
schemaspy.db=main
schemaspy.u=postgres
schemaspy.p=postgres
# schemaspyのコンテナ内での出力先
schemaspy.o=/output
# どのデータベーススキーマに対して生成するか指定。
schemaspy.schemas=odyssage
```

```yaml:docs/dbdoc/docker-compose.yml
services:
  schemaspy:
    build:
      context: .
      dockerfile: ./schemaspy/Dockerfile.dev
    volumes:
      - ../astro/public/odyssage-dbdoc:/output
      - ./schemaspy/schemaspy.properties:/schemaspy.properties
    command: "java -jar schemaspy.jar -vizjs"
    # github actions が立ち上げるコンテナのネットワークに接続するために、host ネットワークを使用する
    network_mode: "host"
```

[package.json 全文](https://github.com/hibohiboo/odyssage/blob/78834487e0b73e2adafa0e10687ea78f3b778cc3/packages/database/package.json)

```diff:packages/database/package.json
{
  "name": "@odyssage/database",
  // 省略
  "scripts": {
    "generate": "drizzle-kit generate",
    "migrate": "cross-env DOTENV_CONFIG_PATH=.env.prod drizzle-kit migrate",
+    "migrate:ci": "cross-env DOTENV_CONFIG_PATH=.env.ci drizzle-kit migrate --config ./drizzle.config.ts"
  },
  "devDependencies": {
    "cross-env": "^7.0.3",
    "dotenv": "^16.4.7",
    "drizzle-kit": "^0.30.5",
    "postgres": "^3.4.5"
  },
  "dependencies": {
    "@neondatabase/serverless": "^0.10.4",
    "drizzle-orm": "^0.41.0"
  }
}
```



[github-pages.yml 全文](https://github.com/hibohiboo/odyssage/blob/78834487e0b73e2adafa0e10687ea78f3b778cc3/.github/workflows/github-pages.yml)

```diff:.github/workflows/github-pages.yml
name: Deploy Documents to Pages
# 省略
jobs:
  build:
    name: Build
    runs-on: ubuntu-latest
+    # dbdoc生成のためにPostgreSQLのコンテナを立ち上げる
+    services:
+      postgres:
+        image: postgres:17
+        env:
+          POSTGRES_USER: postgres
+          POSTGRES_PASSWORD: postgres
+          POSTGRES_DB: main
+        ports:
+          - 5432:5432
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      - uses: oven-sh/setup-bun@v2
        with:
          bun-version: latest

      - name: Setup Pages
        id: pages
        uses: actions/configure-pages@v5

      - name: Install document dependencies
        run: bun install
        working-directory: ${{ env.BUILD_PATH }}

      # ドキュメント作成用の依存関係をインストール
      - name: Install monorepo dependencies
        run: bun install --ignore-scripts

+      # マイグレーションを実行
+      - name: Migration
+        run: bun run migrate:ci
+        working-directory: ./packages/database

+      # dbdoc作成
+      - name: Build dbdoc with Schemaspy
+        run: docker compose up
+        working-directory: ./docs/dbdoc

# 省略
        # ドキュメント作成
      - name: Build with Astro
        run: |
          npm run astro build \
            --site "${{ steps.pages.outputs.origin }}" \
            --base "${{ steps.pages.outputs.base_path }}"
        working-directory: ${{ env.BUILD_PATH }}
#省略
      # astro ドキュメントアップロード
      - name: Upload artifact
        uses: actions/upload-pages-artifact@v3
        with:
          path: ${{ env.BUILD_PATH }}/dist
  deploy:
# 省略
```


# 参考
[GitHubPagesに開発ドキュメントをデプロイする総集編](https://qiita.com/hibohiboo/items/efff5fe687076ab44561)
[Neon(Postgres)のDockerをローカルで稼働させ、Drizzleを使ったマイグレーションとCloudflare Workersのローカル実行からの接続を行ったメモ](https://qiita.com/hibohiboo/items/1827c41ce162431fda3e)
[GitHub ActionsでSchemaSpyのER図を生成してS3にアップロードする](https://zenn.dev/shuhei_takada/articles/ecb030e6529fee)
[tblsで始める楽々データベース設計書管理](https://tech.arms-soft.co.jp/entry/2024/10/23/090000)