By Shy Ruparel, on Jun 1, 2020

Running static site builds with GitHub Actions and Contentful

Someone trying to run static site builds with GitHub actions, Contentful and 11ty

I have been messing around with GitHub Actions since it went into Alpha back in early 2019. It’s GitHub's CI/CD pipeline service that lets you run build, testing and deployment jobs from inside GitHub. I’ve had a chance to create a few projects with it, including our Contentful-Action that lets you run migration scripts against the Contentful CLI.

GitHub Pages initially launched as a way to host projects directly from GitHub Repos. It shipped with a limited version of Jekyll. If you wanted plugins or to use a different SSG, you were out of luck. Thankfully, GitHub Actions has removed a lot of those limitations. When you combine it with Contentful’s webhook features, you can trigger builds every time your team publishes content. This provides powerful and affordable infrastructure for your static site. GitHub Pages usage limits allow for a soft bandwidth limit of 100GB per month and site hosting up to a 1GB. This is a great way to run static sites without any infrastructure cost if you're just getting started or have a small content team.

Last week I worked on a photo gallery powered by Contentful and 11ty. 11ty is a static site generator defined by its minimalism. Unlike other SSGs, 11ty doesn’t depend on any frameworks or dictate specific templating formats. Getting Contentful to provide data, rich-text support and site structure took me about 20 minutes without anything more than the standard Contentful Javascript SDK. Head over to the repo if you’d like to see it in action.

I wanted to share what I learned about configuring GitHub Actions to run static site builds for you and using GitHub Pages to host your sites. You’ll be able to use this pattern regardless of what static site generator you’re using, whether it’s 11ty, Gatsby or Flask-Frozen.

Configuring GitHub Actions for static site builds and GitHub Pages for deployment

Getting GitHub Actions to build and deploy your static site generator is fairly straightforward. We’ll use the GitHub Page action from the GitHub Marketplace. The action comes with examples for most major SSGs. Inside your project, create a workflow file .github/workflows/build-on-push.yml

I’m using the example Static Site Generator with Node.js with a few changes because I’ve configured my package.json to run 11ty with npm build

Since 11ty uses _site as its publish directory, I had to change that in the build file. The GitHub Pages action supports a few different types of tokens. I chose to use a deploy key, so I updated that in the build file. 

You'll need to add an SSH Deploy key so GitHub Actions will be able to deploy to GitHub Pages. This should be a new SSH Key that you only use in this context. It’s important to compartmentalize your SSH keys. That way your work stays safer if one of your personal keys becomes compromised

Add whatever other ENV vars you’ll need for your project to successfully build in the GitHub Secrets page. 

Add whatever other ENV vars you’ll need for your project to successfully build in the GitHub Secrets page.

Commit that file to your repo. When you push it up, it’ll trigger a build and move everything in the publish directory into your GH-Pages branch. 

Commit that file to your repo. When you push it up, it’ll trigger a build and move everything in the publish directory into your GH-Pages branch.Screenshot of Github pages settings

Contentful publish

Now that the static site builds and deploys when you push code to your master branch, it’s only a few more steps to make a rebuild trigger when content is published inside Contentful. First go ahead and add a new workflow file .github/workflows/build-on-publish.yml

This file is identical to our previous workflow file except for one difference. The job now fires on a repository_dispatch event rather than a push. Repository Dispatch acts as GitHub Actions’s way of interfacing with webhooks. We’ll hit an endpoint to trigger a webhook event. 

Head over to your GitHub Developer settings to create a new personal access token and give it the repo scope. You’ll use this token to authenticate when you hit the dispatch endpoint. 

Head over to your GitHub Developer settings to create a new personal access token and give it the repo scope. You’ll use this token to authenticate when you hit the dispatch endpoint.

In the settings menu of your Contentful space, access the webhooks section page and click Add Webhook. Name it “GitHub Action Trigger.” Ensure that you use a POST call with the URL as https://api.github.com/repos/{GitHub User Name}/{Your Repo Name}/dispatches replacing {GitHub User Name} and {Your Repo name} with the information from your repo. Set the triggers to respond only to Publish & Unpublish events on Entries. 

Add the following three headers: 

Accept: application/vnd.github.mercy-preview+json; 

USER-AGENT: Contentful; and 

Authorization: Bearer {GitHub Personal Access Token} replacing {GitHub Personal Access Token} with the token you generated in your developer settings. 

Set the Content type to application/json and the payload to custom with the following json blob {"event_type": "publish-event"}.

Set the Content type to application/json and the payload to custom with the following json blob {"event_type": "publish-event"}.

Hit Save. Hitting publish on any entry now triggers a rebuild via GitHub Actions.

Hitting publish on any entry now triggers a rebuild via GitHub Actions.

Conclusion

These steps give you everything you need to get static sites to build and deploy via GitHub Actions and configure Contentful’s webhook settings to trigger a rebuild when content changes. Head over to GitHub to check out my 11ty repo that has this fully implemented.  

Shy Ruparel
Brooklyn, USA

Shy Ruparel is a Python developer by heart with a passion for day long board games, good jokes and the staying power to wish you a great day on Twitter every single day.