GraphQL スキーマの変更を検知し、TypeScript の型定義を自動的に生成する仕組み
2021年更新版(Kaigi on Rails スポンサートーク資料):GraphQL Schema から TypeScript の型定義を継続的に生成する
English version: Continuously generate TypeScript typings from GraphQL schema across multiple repositories 🚀
GraphQLと TypeScript を使用したアプリケーションを開発するとき、 GraphQL Code Generator (graphql-codegen
) はとても役に立ちます。 GraphQL と TypeScript を併用する場合、 TypeScript で使用する型定義を GraphQL スキーマに基づいて宣言する必要がありますが、 graphql-codegen
はこの型定義を自動で行ってくれます。
graphql-codegen
は便利ですが、 GraphQL API と TypeScript 製のアプリケーションとを別々の GitHub リポジトリ上で開発しているとき、スキーマと型定義との整合性をとるのが難しくなります。 そこで、スキーマと型定義とをリポジトリを跨いで(ほぼ)同期する方法を考えてみます。
graphql-codegen
の基本的な使い方
最小限の設定ファイルは例えばこうなります。
schema
フィールドには、 1) GraphQL API のエンドポイントのURL、 2) *.graphql
または JSON 形式のローカルスキーマファイル、 3) GitHub リポジトリ上の *.graphql
ファイルなどを指定することができます。
詳細は GraphQL Code Generator の公式ドキュメンテーション を参照してください。
準備
次のセクションに進む前に、以下が用意されていることを確認してください。
1. GraphQL API のプロジェクトと、それを管理している GitHub リポジトリ
私のプロジェクトは Rails アプリケーションで、 graphql-ruby
gem を使用しています。 アプリケーションは cont-codegen-sandbox-api
と名付けました。
2. TypeScript を使用したプロジェクトと、それを管理している GitHub リポジトリ
私のプロジェクトは cont-codegen-sandbox-client
と名付けました。
3. GraphQL スキーマ定義ファイルを生成するスクリプト
GraphQL API の実装を元に、 schema.graphql
のような GraphQL スキーマ定義ファイルを生成するスクリプトです。 私の例では lib/graphql/rake_task.rb (rake graphql:schema:idl
) を使用します。
schema.graphql
は、 git の pre-commit hook や GitHub アプリケーションを用いて自動で生成することをおすすめします。
4. GitHub personal access token
リポジトリの Secrets に、 GitHub アカウントの Personal Access Token を設定する必要があります。 私の例では、この secret に PERSONAL_ACCESS_TOKEN
という名前をつけます。
トークンは、 repo
scope の権限を持っている必要があります。
リポジトリが Public か Private かを問わず、 graphql-codegen
と GitHub Action がこのトークンを使用します。
リポジトリを跨いで型定義ファイルを生成する
GraphQL のプロジェクトと TypeScript のプロジェクトが同じディレクトリまたは GitHub リポジトリにある場合、上で紹介した基本的な設定を行うだけで、 GraphQL スキーマに基づいて TypeScript 型定義を作成することができます。 一方で、プロジェクトが別々のリポジトリで管理されている場合はもう少し設定が必要です。
graphql-codegen
の便利な機能のおかげで、GitHub 上の schema.graphql
ファイルを schema
フィールドに指定することができます。 Private リポジトリにも対応しています!✨ codegen.yml
は次のような構文をとります。
graphql-codegen
がリポジトリにアクセスするために、 token
フィールドが必要となります。(このことは公式ドキュメンテーションに書かれていません。 2021年1月現在、リポジトリが Public だとしても token
が必要なようです。 これが不具合なのか仕様なのかは分かりません。)
dotenv を使っている場合、型定義を生成するコマンドは graphql-codegen -r dotenv/config
のようになります。
以下が私の codegen.yml
です:
さて、これで yarn graphql-codegen -r dotenv/config
コマンドによって型定義ファイルを生成することができるようになりました 🔥
リポジトリを跨いで、継続的に型定義ファイルを生成する
前のセクションでは、 GraphQL API と TypeScript 製のアプリケーションが別々のリポジトリで管理されている場合の graphql-codegen
の設定方法を説明しました。 この段階では、型定義ファイルを作成するために毎度コマンドを叩く必要があります。 この作業を自動化しましょう。
型定義ファイル生成の自動化には、 GitHub Action を使うのがよいでしょう。 GitHub Action を使用する場合、これら3つの workflow を定義します:
- GraphQL スキーマの更新を、GraphQL プロジェクトのリポジトリから TypeScript プロジェクトのリポジトリに通知する
graphql-codegen
を実行し、 Pull Request を作成する- Pull Request を自動でマージする(任意)
1. GraphQL スキーマの更新を、TypeScript プロジェクトのリポジトリに通知する
GraphQL スキーマから TypeScript 用の型定義を(ほぼ)同期的に生成するには、スキーマの更新時に GraphQL API のリポジトリから TypeScript プロジェクトのリポジトリに通知する必要があります。
以下の設定によって、 リポジトリがもう一方のリポジトリの repository_dispatch
イベントを発火させることができるようになります。 このイベントは、 コミットが main
ブランチに push され、なおかつ schema.graphql
に差分があったときにのみトリガーされます。
ここで注意すべきことがあります。 3つ目のステップ(Dispatch update-graphql-schema
)では、必ず Personal Access Token を指定する必要があります。 これは、 GITHUB_TOKEN
が repository_dispatch
イベントをトリガーできないためです。
GraphQL API のリポジトリでの設定ファイル .github/workflows/dispatch_graphql_schema_update.yml
はこのようになりました:
2. graphql-codegen
を実行し、 Pull Request を作成する
repository_dispatch
イベントが TypeScript プロジェクトのリポジトリで発火したときに、 graphql-codegen
が最新の GraphQL スキーマを参照して TypeScript の型定義を生成するようにします。
graphql-codegen
の Pull Request が作成されたとき、ある人はそのPRを目視で確認したいかもしれません。 またある人は、そのPRが勝手にマージされてほしいと思うでしょう。 私は後者の方法が好みです。 そこで、 pascalgn/automerge-action
を使用するための設定をいくつか行います。
ここでも気をつけるべきことがあります。 もし自動マージを行いたい場合、4つ目のステップ(Create Pull Request
) では、 Personal Access Token を使用する必要があります。自動マージを行わなくていい場合、 GITHUB_TOKEN
を指定すれば十分です。
TypeScript プロジェクトのリポジトリでの設定ファイル .github/workflows/graphql_schema_updated.yml
は、このようになりました:
3. Pull Request を自動でマージする(任意)
Pull Request を自動でマージしたい場合、 pascalgn/automerge-action
が便利です。 この GitHub Action を使用すると、 automerge
というラベルがついたPRが自動でマージされるようになります。
上で説明した2つ目の workflow は Pull Request を作成して automerge
ラベルをつけますが、そのラベルが付けられた瞬間にこの3つ目の workflow がトリガーされます。
TypeScript プロジェクトのリポジトリでの設定ファイル .github/workflows/automerge.yml
はこのようになります:
動作するサンプル
これでようやく、 継続的にGraphQL スキーマの変更を検知して TypeScript 用の型定義を生成する仕組みが出来上がりました!🚀
正しく設定できていれば、 workflow の画面はこのようになっているはずです。
graphql-codegen
と workflow 設定ファイルへのリンク
graphql-codegen
設定ファイル- GraphQL スキーマの更新を、GraphQL プロジェクトのリポジトリから TypeScript プロジェクトのリポジトリに通知する
graphql-codegen
を実行し、 Pull Request を作成する- Pull Request を自動でマージする
実際に作成された Pull Request へのリンク
上の設定で実際に動かした結果作成されたPRがこれです ayumitamai97/cont-codegen-sandbox-client#36。
※ Create Pull Request
のステップで GITHUB_TOKEN
を使用した場合、コミットの author は自分の GitHub アカウントではなく "github-actions (bot)" になります。
この投稿が役に立ったり、あるいはアドバイスがあれば、ぜひコメントを書いてください。 ここまで読んでくださり、ありがとうございました 👾