GraphQL Code Generator (graphql-codegen
) is very useful when you use GraphQL on the server-side and TypeScript on the client-side. If you use GraphQL and TypeScript, you will declare TypeScript typings based on your GraphQL schema for sure. Instead of writing TypeScript types one by one, graphql-codegen
generates type declarations out of the GraphQL schema which is 1:1 to the schema.
However, you may have problem generating type declarations from the latest GraphQL schema using graphql-codegen
when you develop API and client app in the different GitHub repositories. How should it be solved?
Basic usage of graphql-codegen
A minimal example is:
schema: schema.graphql
generates:
./src/graphql-schema.ts:
plugins:
- typescript
schema
field accepts 1) URL of GraphQL endpoint, 2) local schema file in *.graphql
or JSON format, 3) remote *.graphql
file in GitHub repository, and so on.
Refer to GraphQL Code Generator's documentation for more details.
Prerequisite
Before proceeding to the next section, ensure that you have the following:
1. GraphQL project and its corresponding GitHub repository
Mine is a Rails application along with graphql-ruby
gem, and the app is named cont-codegen-sandbox-api
.
2. Application made with TypeScript and its corresponding GitHub repository
Mine is cont-codegen-sandbox-client
.
3. GraphQL schema generator
A script to generate GraphQL schema file such as schema.graphql
on the server-side. I'm using lib/graphql/rake_task.rb (rake graphql:schema:idl
) for this.
I recommend that you automate this file generation by using git pre-commit hook or GitHub application.
4. GitHub personal access token
Set your GitHub personal access token to your repository's secret. In my case, the secret's name is PERSONAL_ACCESS_TOKEN
.
The token should have access to scope repo
.
graphql-codegen
and GitHub Action use the token whether the repo is private or not.
Generate typings across repos
If your GraphQL project and client app are in the same directory or in the same GitHub repository, the basic example above should be enough. On the other hand, when your applications are managed in different repositories, how should you do?
In that case, you can specify the remote schema.graphql
in a GitHub repository (including private repository โจ). codegen.yml
should be following syntax.
schema:
- user/repo#branchName:path/to/schema.graphql:
token: ${PERSONAL_ACCESS_TOKEN}
token
field is always required because graphql-codegen
can access to your repository, which is not described in the official documentation. Even your repo is public, it requires token
as of today, Jan 2021. I don't know if this is a bug.
If you're using dotenv, codegen command is graphql-codegen -r dotenv/config
.
Here is my codegen.yml
:
schema:
- github:ayumitamai97/cont-codegen-sandbox-api#main:schema.graphql:
token: ${PERSONAL_ACCESS_TOKEN}
generates:
./types/graphql-schema.ts:
plugins:
- typescript
config:
apolloClientVersion: 2
Now, we can generate type declation for TypeScript by hitting yarn graphql-codegen -r dotenv/config
๐ฅ
Continuously generate typings across repos
The previous section describes how to setup graphql-codegen
when having GraphQL and TypeScript projects in different repositories. Then, how can this process be automated?
GitHub Action may be the best way to do that. We need to create three GitHub workflows:
- Notify client-side repo when GraphQL schema is updated (server-side repo)
- Execute
graphql-codegen
and create Pull Request (client-side repo) - Automerge Pull Request (client-side repo) (optional)
1. Notify client-side repo when GraphQL schema is updated
To generate TypeScript typings out of GraphQL schema almost synchronously, server-side repo has to notify client-side repo when GraphQL schema is updated.
The configuration below allows the repo to trigger repository_dispatch
event in the other repo when a commit is pushed to main
branch and schema.graphql
has file diff.
Caveat! The third step (Dispatch update-graphql-schema
) requires your personal access token since GITHUB_TOKEN
cannot trigger repository_dispatch
event.
My .github/workflows/dispatch_graphql_schema_update.yml
in server-side repo:
name: Dispatch GraphQL Schema Update
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: technote-space/get-diff-action@v4.0.1
with:
PATTERNS: schema.graphql
- name: Dispatch update-graphql-schema
uses: peter-evans/repository-dispatch@v1
with:
repository: ayumitamai97/cont-codegen-sandbox-client
token: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
event-type: update-graphql-schema
if: env.GIT_DIFF
2. Execute graphql-codegen
and create Pull Request
When repository_dispatch
event is triggered in the client-side repo, we want graphql-codegen
to generate TypeScript types based on the latest GraphQL schema.
When the Pull Request is created, one wants to check & approve the PR, while another wants PR to be merged automatically. I like the latter idea, so I added some configurations to prepare for pascalgn/automerge-action
.
Caveat! The 4th step (Create Pull Request
) requires PERSONAL_ACCESS_TOKEN
if you want to automerge the Pull Request. Otherwise, GITHUB_TOKEN
is enough.
My .github/workflows/graphql_schema_updated.yml
on client-side repo:
name: Update GraphQL Schema
on:
repository_dispatch:
types: [update-graphql-schema]
jobs:
update-graphql-schema:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v2
- name: Install dependencies
run: yarn install
- name: Update GraphQL Schema
run: PERSONAL_ACCESS_TOKEN=${{ secrets.PERSONAL_ACCESS_TOKEN }} yarn codegen
- name: Create Pull Request
uses: peter-evans/create-pull-request@v3
with:
token: ${{ secrets.PERSONAL_ACCESS_TOKEN }} # `GITHUB_TOKEN` unless using automerge-action
commit-message: '[bot] Update GraphQL Schema'
committer: GitHub <noreply@github.com>
author: ${{ github.actor }} <${{ github.actor }}@users.noreply.github.com>
signoff: false
branch: feature/update-graphql-schema
branch-suffix: timestamp
delete-branch: true
title: '[bot] Update GraphQL Schema'
body: GraphQL schema has been updated
labels: automerge # required if using automerge-action
3. Automerge Pull Request (optional)
If you'd like a Pull Request to be automerged which is created in GitHub workflows, pascalgn/automerge-action
is helpful. This GitHub Action merges a PR automatically when it has automerge
label.
As the second workflow creates a new Pull Request and adds automerge
label to it, the third (this) workflow should be triggered when a PR is labeled.
My .github/workflows/automerge.yml
on client-side repo:
name: Automerge
on:
pull_request:
types:
- labeled
jobs:
automerge:
runs-on: ubuntu-latest
steps:
- name: automerge
uses: pascalgn/automerge-action@v0.13.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Working example
Finally, your GraphQL project can continuously generate TypeScript typings out of GraphQL schema across repositories! ๐
If you successfully configured all of the above, workflows should look like this.
Links to my codegen & workflow configurations
Link to the example Pull Request
You can see the actual Pull Request created in the workflow here ayumitamai97/cont-codegen-sandbox-client#36.
Note that if you use GITHUB_TOKEN
for Create Pull Request
step, the committer will be "github-actions (bot)" instead of your account.
If this post is helpful, or you know better ways to do these things, please don't hesitate to leave a comment. Thank you for reading! ๐พ
Japanese version: GraphQL ในใญใผใใฎๅคๆดใๆค็ฅใใTypeScript ใฎๅๅฎ็พฉใ่ชๅ็ใซ็ๆใใไป็ตใฟ | Medium
Top comments (1)
LOVE IT. Thank you!