graphql-rubyのスキーマ変更をGraphQL Inspectorで自動チェックする
モチベーション
GraphQL API の改修をする際はスキーマの変更に注意する必要があります。
特に破壊的変更はクライアントに影響が出る可能性があります。そうであると気づかずにリリースしてしまうと障害になりかねません。
通常はコードレビューまでの過程で気がつくケースが多いと思いますが、CI でチェックしたほうが漏れを減らせそうです。
この記事では、graphql-ruby を用いた GraphQL API 開発におけるスキーマの変更を、GraphQL Inspector を使って CI で自動的にチェックする方法について説明します。
実装
graphql-ruby でスキーマファイルを生成する
スキーマ変更をチェックするためには、まずスキーマファイルを生成する必要があります。
graphql-ruby では、デフォルトでスキーマファイルが生成されないため、インストール後に設定が必要です。
幸いにも、graphql-ruby にはGraphQL::RakeTaskクラスが用意されており、次のようなファイルを作成することで、スキーマファイルを生成する Rake タスクを利用できます。
require 'graphql/rake_task'
# app/graphql/myapp_schema.rbにMyappSchemaが定義されているとする
GraphQL::RakeTask.new(schema_name: 'MyappSchema', directory: 'app/graphql', idl_outfile: 'myapp_schema.graphql')
次のコマンドでスキーマファイルを作成できます。
$ bundle exec rake graphql:schema:idl
Schema IDL dumped into app/graphql/myapp_schema.graphql
と表示されたら成功です。
生成されたスキーマファイルは次のような内容になります。
"""
An ISO 8601-encoded datetime
"""
scalar ISO8601DateTime @specifiedBy(url: "https://tools.ietf.org/html/rfc3339")
type Mutation
type Post {
body: String
createdAt: ISO8601DateTime!
id: ID!
title: String!
updatedAt: ISO8601DateTime!
}
type Query {
post(id: ID!): Post!
}
スキーマファイルが更新されていることを担保するテスト
スキーマ変更を伴うコードの変更をした場合は、スキーマファイルを更新する必要があります。
更新漏れを検知するために、スキーマファイルが現在のコードの状態と一致しているかをチェックする Rspec を書きます。
なお、CI や pre-commit hooks で自動更新されるようにすると、手動でタスクを実行する手間が省けて良いと思いますが、この記事では省略します。
require 'rails_helper'
RSpec.describe MyappSchema do
describe 'GraphQL Schema file' do
it 'is up to date' do
current_defn = described_class.to_definition
printout_defn = Rails.root.join('app/graphql/myapp_schema.graphql').read
expect(current_defn).to eq(printout_defn), 'Update the printed schema with `bundle exec rake graphql:schema:idl`'
end
end
end
GraphQL Inspector を使ってスキーマの変更をチェックする
GraphQL Inspectorは GraphQL スキーマの変更点を出力するツールです。
破壊的変更などを検出してくれる機能などがあります。
GitHub Actions の Action が用意されており、Pull Request に含まれる破壊的変更を検出することができます。
次のように GitHub Actions のワークフロー作成します。
実行するにはWorkflow permissions
をRead and write permissions
にする必要があります。
https://github.com/[Owner]/[Repository]/settings/actions
から変更できます。
name: Check GraphQL Schema
on:
pull_request:
paths:
- "app/graphql/myapp_schema.graphql"
jobs:
test:
name: Check Schema
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@master
- uses: kamilkisiela/graphql-inspector@master
with:
schema: "develop:app/graphql/myapp_schema.graphql" # 変更前のスキーマのブランチとファイルパス
fail-on-breaking: false # 破壊的変更が検出された場合でもステップを失敗ステータスにしない
なお、詳しいオプションは公式ドキュメントを参照してください。
変更前のスキーマをファイルパスで指定する代わりに、GraphQL の API エンドポイントを指定するオプションなどもありました。
チェック結果の例
実験的に次の変更をしたときのチェック結果の例です。
非破壊的変更
- field の追加
破壊的変更
- non-null な field を nullable に変更(タイプ変更)
- field の削除
- required な argument を追加
実際に変更したコードの内容です。
GraphQL Inspector によるチェック結果は次の通りです。
Pull Request のインラインコメントで変更箇所を教えてくれます。破壊的変更は ✗ マークと赤色で表示されているのですぐに気づけます。
さらに、field を削除している箇所については、まず deprecated にすることを勧めてくれています。
まとめ
graphql-ruby でスキーマファイルを生成し、GraphQL Inspector の GitHub Actions を使って変更をチェックする方法をまとめました。
スキーマの破壊的変更や危険な変更を自動的に検出することで、より安全に GraphQL API の開発を進めることができそうです。
参考
以上
Discussion