弊社では、データの分析をメンバーがしやすくするにあたって、Re:dashを導入しています。
データへのアクセスのしやすさ、SQLの実行のしやすさはRe:dashで良いとして、 実際にどんなデータがどんなテーブルにはいっているのかを知らなければ分析方法をまちがってしまったり、 分析をするためにコミュニケーションが煩雑になりスケールしづらく、分析のハードルがあがってしまいます。
一方で、データベースのスキーマはプロダクトを日々開発をしていく中で追加になったり変更になったりする事がおおく、 変更にドキュメントを追従させていくコストをなるべく減らしていく事も必要です。
また、結果を社内のメンバーしかアクセスできないようにするために 社内サーバーを立てて、デプロイプロセスを設計して等のコストを書けるには、サービス初期という事もありまだ早いとかんがえました。
そこで、今回はRailsアプリケーションのDBスキーマ変更をGitHub Actionsで検知してSchemaSpyをつかって文書化し、 Slackのチャンネルに結果をアップロードするようにしてみました。
Schema Spy
データベースのドキュメント生成として、けっこう有名なツールになるかとおもいますが
DBに接続して、スキーマやテーブルの関連を調査してHTMLドキュメントを生成してくれるツールです。 JarやDockerコンテナとして配布されているので、CI上でも比較的動かしやすいツールとなっています。
メタ情報
Schema SpyをそのままつかうとDBのテーブルのリスト等を集めてくれるのですが、 この段階では DBのテーブルやカラムに Comment が付いていなければ、ただテーブルの一覧やカラムの一覧、関連のER図を生成してくれるのみです。 それだけでも非常に有用なのですが、またenum系のカラムの数値が何を意味しているのか等の情報はわかりません。
また、このDBにコメントをつけていくという作業、 Railsのmigrationでも可能なのですがmigrationを大量に発行して全てのカラムにコメントをつけるよりも、 SchemaSpyにXMLで投入する事で追加して読みこんでもらえるため、そちらのプランでいこうとおもいました。
そんな時に、このデータをYAMLからXMLを生成してしまうという手法をみかけ、そちらを採用させていただきました!
Github Actions
今回はRailsのアプリケーションでDBのスキーマを管理している db/schema.rb
の変更を検知して変更がmasterブランチに発生したら、
SchemaSpyを実行して、結果をZipでまとめてSlackに投稿するようにしました。
以下Github Actionsのコードの抜粋です。
name: upload-schemaspy on: push: branches: [master] paths: - "db/schema.rb" - "db/schemaspy_meta.yml" - "lib/tasks/schemaspy_meta_xml.rake" jobs: schemaspy: runs-on: ubuntu-latest services: mysql: image: mysql:5.7 options: >- --health-cmd "mysqladmin ping -h localhost" --health-interval 20s --health-timeout 10s --health-retries 10 env: MYSQL_USER: root MYSQL_ROOT_PASSWORD: XXXXXXXXXXXXXX ports: - 3306 container: image: ruby:2.6.6 env: RAILS_ENV: test RAILS_MASTER_KEY: XXXXXXXXXXXXXXXXXXXXXXXXXXXX steps: - uses: actions/checkout@v2 - name: Bundler Cache uses: actions/cache@v1 id: cache-bundler with: path: vendor/bundle key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }} restore-keys: | ${{ runner.os }}-gems- - name: Setup Bundler run: | gem install bundler bundle config set path 'vendor/bundle' - name: Bundle install if: steps.cache-bundler.outputs.cache-hit != 'true' run: bundle install --jobs=4 --retry=3 - name: Setup database run: | cp config/database.yml.ci config/database.yml bundle exec rails db:prepare - uses: actions/setup-java@v1 with: java-version: '9.0.4' # The JDK version to make available on the path. java-package: jdk # (jre, jdk, or jdk+fx) - defaults to jdk architecture: x64 - name: schemaSpy run: | wget https://github.com/schemaspy/schemaspy/releases/download/v6.1.0/schemaspy-6.1.0.jar -O schemaspy.jar wget https://dev.mysql.com/get/Downloads/Connector-J/mysql-connector-java-5.1.48.zip -O mysql-connector-java-5.1.48.zip unzip mysql-connector-java-5.1.48.zip bundle exec rails schemaspy_meta_xml:generate java -jar schemaspy.jar -configFile ./.github/schemaspy.properties -vizjs -meta ./db/schemaspy_meta.xml -norows mkdir -p artifact/schemaspy mv output/* artifact/schemaspy/. - uses: montudor/action-zip@v0.1.1 with: args: zip -qq -r artifact/schema-information.zip artifact/schemaspy - name: Upload to slack uses: adrey/slack-file-upload-action@master with: token: ${{ secrets.SLACK_TOKEN }} path: artifact/schema-information.zip channel: XXXXX
SchemaSpyはJarでダウンロードして実行するようにしており、
Javaのセットアップ、Zipによる圧縮、Slackへの投稿に以下のActionを利用させていただいています。
実行結果
SlackのAppを作成して、TokenをGithub ActionsのScretsに設定して、データスキーマ共有のチャンネルにJoinさせ、実行してみると無事投稿されてきます。