Trigger Repository Dispatch Event on Github Actions from Sanity.io through Node Express as Workaround
Want to start the build process from your headless CMS automatically after you created new content? Here is a solution that works with Sanity.io, Gatsby and a Github repository.
Nowadays, it is quite easy to deploy your web application from the Github repository to a provider like Netlify or Heroku with one click as part of the Jamstack Web Development. With the help of Github Actions, this process can even be automated to the extent that the deployment is triggered on every push or other event without any further action.
Node Express server as workaround solution
This can be done by an intermediate Node Express Server, which acts as kind of proxy server between the headless CMS and Github Actions on let´s say Heroku or Netlify and triggers the build process on Github Actions1. With the magic of a repository dispatch after changes are made to the content.
If no further action is taken, the build process occurs on the Headless CMS for every small change. Triggering such an action every five seconds after each change is of course not wanted. The queue would get too long. However, the recently added concurrency
parameter in Github Actions comes to the rescue. Setting the attribute to no-double-trigger
you are good to go and further race conditions are avoided down the road.
Here's the short script that runs on an Express server, waits for the POST webhook from Sanity.io, and forwards it to Github Actions along with a Github token necessary for triggering the repository dispatch on Github Actions.
require('dotenv').config();
const express = require('express');
const axios = require('axios');
const app = express();
app.all('*', handleRouting);
function handleRouting(req, res) {
if (req.method === 'POST' && req.originalUrl === '/trigger_deploy') {
const url = `${process.env.GITHUB_REPOSITORY_URL}`;
const body = { event_type: 'trigger_deploy' };
const options = {
headers: {
Accept: 'valueapplication/vnd.github.v3+json',
'Content-Type': 'application/json',
Authorization: `Bearer ${process.env.GITHUB_TOKEN}`,
},
};
axios.post(url, body, options);
res.send('Deployment triggered');
} else {
res.sendStatus(403);
}
}
app.listen(process.env.PORT, () => console.log(`Server started on port ${process.env.PORT}`));
Make sure to set the environmental variables GITHUB_REPOSITORY_URL
, GITHUB_TOKEN
and PORT
accordingly with proper values.
Configuration file on Github Actions
The configuration of the Github Actions workflow looks as follows. In this case it´s a Gatsby frontend app deployed on an AWS S3 bucket together with CDN Cloudfront service. However, it´s easy to adapt the yaml file to other frontend frameworks like Node.js or Vue, parameters and environmental variables must be adjusted accordingly of course. No need to reinvent the wheel every time.
# from https://github.com/marketplace/actions/s3-sync
name: Upload Website
on:
push:
branches:
- main # might be `master` for older repos
repository_dispatch:
types: [trigger_deploy]
concurrency:
group: no-double-trigger
cancel-in-progress: true
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Use Node.js
uses: actions/setup-node@v1
with:
node-version: 14.x
- name: Cache node modules
uses: actions/cache@v1
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: ${{ runner.os }}-node-
- name: Build
run: |
npm ci
npm run build
env:
GATSBY_SANITY_PROJECTID: ${{ secrets.GATSBY_SANITY_PROJECTID }}
GATSBY_SANITY_DATASET: ${{ secrets.GATSBY_SANITY_DATASET }}
GATSBY_ENV: production
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: eu-central-1
- name: Deploy
uses: jonelantha/gatsby-s3-action@v1
with:
dest-s3-bucket: ${{ secrets.S3_BUCKET_NAME }}
cloudfront-id-to-invalidate: ${{ secrets.CLOUDFRONT_ID }}
Github repository of the Gatsby frontend application.
Find here the corresponding yaml configuration file on Github Actions.