graphql-inspector
graphql-inspector copied to clipboard
Github action: Allow globs in schema
Is your feature request related to a problem? Please describe.
Often graphql schema's are split in multiple files.
Describe the solution you'd like
Allow to specify the schema using a glob as in schema: main:api/**/*.graphql.
Describe alternatives you've considered
Currently, globs are not supported as the above schema leads to the following error:
Error: ENOENT: no such file or directory, open '/home/runner/work/JabRefOnline/JabRefOnline/api/**/*.graphql'
Query main:api/**/*.graphql from JabRef/JabRefOnline
{ repository: { object: null } }
Error: result.repository.object.text is null
at /home/runner/work/_actions/kamilkisiela/graphql-inspector/v2.6.2/action/index.js:1:357422
at Generator.next (<anonymous>)
at fulfilled (/home/runner/work/_actions/kamilkisiela/graphql-inspector/v2.6.2/action/index.js:1:254624)
at processTicksAndRejections (internal/process/task_queues.js:93:5)
It would be also nice if the schema could automatically be picked up from a graphql.config file.
Additional context
Moreover, the schema field is not documented.
The diff CLI actually supports this now:
✗ graphql-inspector diff 'git:origin/main:./src/main/resources/**/*.graphqls' 'src/main/resources/**/*.graphqls'
Detected the following changes (2) between schemas:
✖ Field email was removed from object type User
✔ Field User.name changed type from String to String!
error Detected 1 breaking change
I'm not sure why the GitHub App or Action don't, @kamilkisiela can you please shed some light on this as I do agree with @tobiasdiez this is a pretty common use case.
There's one reason, you can't use a glob in GitHub's GraphQL API to get files and their content. Of course it's a common use case.
In Action it could be possible but then you would have to fetch a lot of previous commits and people usually set the depth to 1 to improve the speed of git checkout in CI/CD.
Thanks @kamilkisiela for checking that. Would it be possible then to provide a folder where the files are placed instead and use the API to list the contents of that folder?
Potentially yes
I'm open for Pull Requests
Thanks for having a look at this.
In the context of the github action, it would be great if the git history is used directly instead of passing through the graphql api to get the necessary files. There are some plans to allow fetching multiple branches using the checkout action without having to set fetch-depth: 0 https://github.com/actions/checkout/pull/155, and this can be also improved by manually running something like git fetch --no-tags --prune --depth=1 origin +refs/heads/*:refs/remotes/origin/*. Thus I don't think its a problem to assume that the necessary history is present.
@kamilkisiela wouldn't be enough pointing in the documentation that depth=1 is not allowed if used with github actions and glob?
It's an acceptable tradeoff imo.
If your are usingendpoint as a base (assuming you don't want to git track a combined schema file) then you can merge your schema files into one using a simple script:
bin/combine-graphql-files.js
const { mergeTypeDefs } = require('@graphql-tools/merge');
const { loadFilesSync } = require('@graphql-tools/load-files');
const { print } = require('graphql');
const { writeFileSync } = require('fs');
const typeDefs = mergeTypeDefs(loadFilesSync(`${process.cwd()}/src/**/*.graphql`));
writeFileSync(`${process.cwd()}/combined.graphql`, print(typeDefs))
Then in call it right before in your workflow and reference the file in graphql-inspector step:
- name: Combine .graphql files for validation
run: node bin/combine-graphql-files.js
- name: Validate graph changes
uses: kamilkisiela/graphql-inspector@master
with:
schema: 'combined.graphql'
endpoint: 'https://yousite.com/graphql
Or if you prefer inline instead of referencing a file
- name: Combine .graphql files (typedefs) for validation
uses: actions/github-script@v6
with:
script: |
const { mergeTypeDefs } = require('@graphql-tools/merge');
const { loadFilesSync } = require('@graphql-tools/load-files');
const { print } = require('graphql');
const { writeFileSync } = require('fs');
const typeDefs = mergeTypeDefs(loadFilesSync(`${process.cwd()}/src/**/*.graphql`));
writeFileSync(`${process.cwd()}/combined.graphql`, print(typeDefs))
- name: Validate graph changes
uses: kamilkisiela/graphql-inspector@master
with:
schema: 'combined.graphql'
endpoint: 'https://yousite.com/graphql
Thanks for the suggestion, but my usecase is exactly merging many schema files that are in the same repo.
If it helps, here's a sample config from one of our repos that merges multiple schema files together across different branches using two different checkout steps:
name: GraphQL Inspector
on:
pull_request:
paths:
- 'api/**.gql'
jobs:
check-schema:
name: Check Schema for Breaking Changes
runs-on: ubuntu-latest
steps:
- name: Checkout Base Commit
uses: actions/checkout@v2
with:
ref: ${{ github.event.pull_request.base.sha }}
path: base_tree
- name: Checkout PR Commit
uses: actions/checkout@master
with:
path: pr_tree
- uses: ruby/setup-ruby@v1
with:
ruby-version: 2.7
bundler-cache: true
working-directory: pr_tree
- name: Compare Schema
id: compare
continue-on-error: true
shell: bash {0}
working-directory: pr_tree/ruby
run: |
oldSchema=$(cat ../../base_tree/api/*.gql)
newSchema=$(cat ../api/*.gql)
compareOutput="$(bundle exec schema_comparator verify "$oldSchema" "$newSchema" 2>&1)"
compareExit=$?
# https://github.community/t/set-output-truncates-multiline-strings/16852/3
compareOutput="${compareOutput//'%'/'%25'}"
compareOutput="${compareOutput//$'\n'/'%0A'}"
compareOutput="${compareOutput//$'\r'/'%0D'}"
echo "::set-output name=stdout::$compareOutput"
exit $compareExit
- uses: hasura/comment-progress@v2
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
repository: ${{ github.repository }}
number: ${{ github.event.number }}
id: gql-changes
recreate: true
message: |
### GraphQL Changes Summary
```
${{steps.compare.outputs.stdout}}
```
It's currently using https://github.com/xuorig/graphql-schema_comparator but could easily be modified to use graphql-inspector instead (using the snippet above I think). In our repo structure, schema files live in an api folder under the root.
@kamilkisiela is there any plan for making this feature available? All the current workaround proposed don't really play well with the github action features. Combining manually the schema before would break the annotations. Also, the main GraphQL I've seen so far is breaking schemas in multiple files. All the Guild tooling support this scenario but the Github action. It's a shame as we are not able to use the very useful features like the annotation, but we are forced of using manual CI step with a text output.