From qa-contract-testing
Diffs two GraphQL schemas with `graphql-inspector diff`, classifies each change as BREAKING / DANGEROUS / NON_BREAKING, and applies opt-in rules (suppress-removal-of-deprecated-field, consider-usage, ignore-description-changes) to gate CI on schema regressions. Use when reviewing GraphQL schema changes in a PR or evaluating Federation supergraph drift.
How this skill is triggered — by the user, by Claude, or both
Slash command
/qa-contract-testing:graphql-schema-regressionThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
GraphQL Inspector is a schema-management CLI from The Guild that
GraphQL Inspector is a schema-management CLI from The Guild that validates GraphQL schemas and detects changes between two versions (gqi-overview). It classifies every change into one of three tiers (gqi-diff):
| Classification | Meaning |
|---|---|
| Breaking | Will disrupt existing clients (removed fields, narrowed types). |
| Dangerous | Won't immediately break clients but may cause issues (e.g. union member added). |
| Non-breaking | Safe additions (new fields on existing types, new types). |
The tool exits non-zero when breaking changes exist, exits zero otherwise - the gate is the exit code.
This is the GraphQL-specific counterpart to
openapi-contract-diff. Use it
when the API surface is GraphQL (single schema or Apollo Federation
supergraph) instead of REST.
schema.graphql, an SDL string in
code, or a Federation subgraph).@deprecated) and
wants suppressRemovalOfDeprecatedField semantics - i.e. removing a
field that has been marked @deprecated long enough is acceptable,
removing a non-deprecated field is not.npm install --global @graphql-inspector/cli
(Per gqi-overview.)
For ad-hoc CI use, prefer running it via npx @graphql-inspector/cli
without a global install.
graphql-inspector diff schema.old.graphql schema.new.graphql
(Per gqi-diff.)
The command supports SDL files, introspection result JSON, GitHub
URLs, and live endpoints - when passing an endpoint use the --header
flag to attach an auth token.
# Pull the production schema first
graphql-inspector introspect https://api.example.com/graphql > schema.prod.graphql
# Diff against the local SDL
graphql-inspector diff schema.prod.graphql schema.graphql
The default output is human-readable, grouped by classification. Find breaking changes, dangerous changes, and non-breaking changes printed under separate headings.
For machine consumption, the JSON-output GitHub Action
(kamilkisiela/graphql-inspector or
@graphql-inspector/github-action) produces a structured report; for
arbitrary CI, parse the human-readable output via grep on the
classification headings.
graphql-inspector diff accepts --rule flags to customize the gate
(gqi-diff):
| Rule | Effect |
|---|---|
dangerousBreaking | Treat dangerous changes as breaking (stricter). |
suppressRemovalOfDeprecatedField | Removing a @deprecated field is non-breaking. |
ignoreDescriptionChanges | Don't flag pure description / docstring edits. |
safeUnreachable | Treat changes to unreachable parts of the graph as safe. |
considerUsage | Use real-client usage data (Apollo Studio, etc.) to grade severity. |
Custom rules live as JS modules:
graphql-inspector diff old.graphql new.graphql --rule './rules/our-custom.js'
A custom rule exports a function ({ changes }) => filteredChanges -
useful when the team has a project-specific severity policy
(e.g. "removing any field under internalAdmin* is non-breaking").
# .github/workflows/graphql-diff.yml
name: graphql-schema-diff
on:
pull_request:
paths:
- 'schema.graphql'
- '**/*.graphql'
jobs:
inspector:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
with:
fetch-depth: 0
- uses: actions/setup-node@v4
with:
node-version: '20'
- name: Extract base schema
run: |
BASE_SHA=$(git merge-base origin/main HEAD)
git show $BASE_SHA:schema.graphql > /tmp/schema-base.graphql
- name: Diff
run: |
npx @graphql-inspector/cli diff \
/tmp/schema-base.graphql \
schema.graphql \
--rule suppressRemovalOfDeprecatedField \
--rule ignoreDescriptionChanges
The --rule suppressRemovalOfDeprecatedField is the canonical pattern
for projects that take deprecation seriously: removing a field with
@deprecated is allowed; removing a live field blocks the PR.
For Apollo Federation, run graphql-inspector diff once per subgraph,
not against the supergraph composite - the composite includes all
subgraph types and a single subgraph PR's "added type" would appear as
"already present" on the composite side.
# For each subgraph in the PR
for subgraph in subgraphs/*/schema.graphql; do
echo "Checking $subgraph"
graphql-inspector diff "/tmp/${subgraph#subgraphs/}-base" "$subgraph"
done
Pair the per-subgraph diff with rover supergraph compose (Apollo's
official CLI) to confirm the composition still produces a valid
supergraph after the PR's changes.
graphql-cli - older umbrella tool; superseded by @graphql-inspector/cli.rover graph check - Apollo Studio's hosted equivalent;
use this when the project is on Apollo Studio for the usage-based
considerUsage analog.This skill stays focused on graphql-inspector because it's the
self-hosted, vendor-neutral default.
diff CLI semantics, change classifications,
rule flags.openapi-contract-diff - REST
counterpart for OpenAPI.contract-compatibility-gate - gate skill that aggregates this output with Pact / oasdiff verdicts.npx claudepluginhub testland/qa --plugin qa-contract-testingProvides a checklist for code reviews covering functionality, security, performance, maintainability, tests, and quality. Use for pull requests, audits, team standards, and developer training.