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.

Tuedo#007

 by  tuedodev

11
Sep 2021
 0

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.

  1. A very similar approach you can find here. The approach of the authors with Dockers and Kubernetes is fascinating, but for my humble purpose it would have been a little bit overengineered.

This post has not been commented on yet.

Add a comment