graphql-inspector icon indicating copy to clipboard operation
graphql-inspector copied to clipboard

Github action: Allow globs in schema

Open tobiasdiez opened this issue 4 years ago • 12 comments
trafficstars

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.

tobiasdiez avatar Aug 05 '21 14:08 tobiasdiez

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.

paul-pop avatar Oct 22 '21 09:10 paul-pop

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.

kamilkisiela avatar Oct 22 '21 15:10 kamilkisiela

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?

paul-pop avatar Oct 22 '21 15:10 paul-pop

Potentially yes

kamilkisiela avatar Oct 22 '21 15:10 kamilkisiela

I'm open for Pull Requests

kamilkisiela avatar Oct 22 '21 15:10 kamilkisiela

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.

tobiasdiez avatar Oct 22 '21 16:10 tobiasdiez

@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.

lughino avatar Nov 12 '21 17:11 lughino

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

prescottprue avatar Mar 24 '22 06:03 prescottprue

Thanks for the suggestion, but my usecase is exactly merging many schema files that are in the same repo.

tobiasdiez avatar Mar 24 '22 12:03 tobiasdiez

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.

jayzes avatar Mar 24 '22 15:03 jayzes

@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.

lughino avatar Nov 03 '22 17:11 lughino