graphql-doctor
Catch GraphQL-Ruby resolver contract mismatches before runtime
Features · Installation · Quick Start · Commands · Configuration · CI · Diagnostics
graphql-doctor connects GraphQL-Ruby's runtime schema with Prism-parsed Ruby source. It catches missing resolver methods, incompatible keywords, invalid callback signatures, and unregistered members before a query reaches production.
Features
- Maps runtime fields and arguments back to exact Ruby source locations
- Checks resolver method existence and visibility
- Verifies keywords after
loads:,as:,extras:, defaults, and nullability - Validates
prepare:,ready?,authorized?, and opt-in execution callbacks - Finds unregistered resolver and mutation classes
- Reports as text, JSON, SARIF, or GitHub Actions annotations
- Supports schema dumps for CI jobs that cannot boot the application
- Parses in parallel and caches source indexes
Installation
Add the gem to the application that owns the schema:
group :development, :test do
gem "graphql-doctor"
endThen install it:
bundle installRequirements
- Ruby 3.1+
- GraphQL-Ruby 2.0+
- Prism is the only runtime dependency
On Ruby 3.4, use GraphQL-Ruby 2.0.32 or newer. GraphQL-Ruby 2.0.x also needs racc on Ruby 3.4.
Quick Start
Create .graphql-doctor.yml in the application root:
schema: MyAppSchema
require: ./config/environmentRun the contract checks:
bundle exec graphql-doctor checkBy default, Ruby files under app/graphql/**/*.rb are indexed and errors cause exit status 1.
Commands
| Command | Description |
|---|---|
graphql-doctor check [paths] |
Check resolver contracts; this is the default command |
graphql-doctor dump-schema |
Write the reflected runtime schema as JSON |
graphql-doctor coverage |
Show source-to-runtime field mapping coverage |
graphql-doctor explain CODE |
Print the reference for a diagnostic code |
graphql-doctor version |
Print the installed version |
Common options:
bundle exec graphql-doctor check app/graphql --format github
bundle exec graphql-doctor check --only GQLD301,GQLD303
bundle exec graphql-doctor check --fail-level warning
bundle exec graphql-doctor check --no-cache --jobs 4
bundle exec graphql-doctor check --format sarif --out tmp/results.sarifOutput formats are text, json, sarif, and github. NO_COLOR and --no-color disable ANSI output.
Exit statuses are 0 when the configured threshold is clear, 1 when diagnostics meet --fail-level, and 2 for configuration, boot, or execution failures.
Configuration
| Option | Type | Default | Description |
|---|---|---|---|
schema |
String | null |
GraphQL schema constant to inspect |
require |
String | ./config/environment |
File loaded before resolving the schema |
include |
String[] | app/graphql/**/*.rb |
Ruby source paths or glob patterns to index |
exclude |
String[] | [] |
Paths or glob patterns to skip |
checks |
Mapping | See below | Per-code enabled and severity overrides |
allow_underlying_object |
String[] | [] |
Types allowed to resolve through their backing objects |
abstract_classes |
String[] | [] |
Base resolvers and mutations excluded from registration checks |
experimental.new_execution_api |
Boolean | false |
Enable checks for the experimental execution callback |
require_suppression_reason |
Boolean | false |
Ignore suppression comments without a reason |
Example configuration:
schema: MyAppSchema
require: ./config/environment
include:
- app/graphql/**/*.rb
exclude:
- app/graphql/legacy/**/*.rb
checks:
GQLD201: { severity: warning }
GQLD305: { enabled: true }
allow_underlying_object:
- Types::UserType
abstract_classes:
- Mutations::BaseMutation
require_suppression_reason: trueGQLD102, GQLD103, and GQLD305 are disabled by default. Use --only or checks to enable them.
CI
Use GitHub annotations for a single-job check:
bundle exec graphql-doctor check --format githubFor split CI, boot the application once and pass the schema dump to the checking job:
bundle exec graphql-doctor dump-schema --out tmp/schema.json
bundle exec graphql-doctor check --no-boot --schema-dump tmp/schema.jsonRunning check --no-boot without a schema dump performs static checks only. Cache files are stored under .graphql-doctor/cache; add .graphql-doctor/ to the target application's .gitignore.
Diagnostics
See the diagnostic reference for every code, its runtime impact, possible false positives, and fixes.
bundle exec graphql-doctor explain GQLD301Suppress one line or a whole file when the behavior is intentional:
def resolve(id:) # graphql-doctor:disable GQLD301 -- handled by an extension
# graphql-doctor:disable-file GQLD201 -- objects provide all fieldsHow It Works
- Prism indexes GraphQL DSL calls, Ruby methods, callbacks, and source locations.
- GraphQL-Ruby provides the booted runtime schema, or
--schema-dumpsupplies an earlier snapshot. - The correlator joins source definitions to runtime fields and arguments.
- Contract checks produce diagnostics without executing application queries.
The runtime schema is the source of truth for GraphQL behavior; Prism is the source of truth for Ruby structure and locations.
Development
bundle install
bundle exec rake testFor the GitHub Pages landing page, see site development and publishing.
Contributing
Bug reports and pull requests are welcome at https://github.com/ydah/graphql-doctor.
License
Released under the MIT License.