Automatic Publishing With Jigsaw, Netlify and GitHub Actions cover image

January 21, 2020

Automatic Publishing With Jigsaw, Netlify and GitHub Actions


When I first setup this blog (just a couple of weeks back) I was using a combination of; Tighten Jigsaw, GitHub Actions & Pages. That setup allowed me to initially get my blog up and running very quickly, letting me focus solely on the content. However, soon after I published that post @the_nabeelahmed suggested using Netlify over GitHub Pages and provided me with the minimum configuration details needed to get Netlify working.

As I had some time that evening, I checked out Netlify and was genuinely able to get my blog published and switched over in a matter of minutes. That is a developer experience I loved.

Now, I know that some of you are saying / screaming:

James, you've only just started blogging, focus on the content and stop optimizing early!

To you, I say: thanks for the concern, but I'm optimising my writing workflow to allow me to focus on the content whilst reaping all the benefits of a static site and in doing so, I'm able to write about my experiences. Yes, I could use Wordpress, but that requires even more work to customise to my liking (and I never want to use hosted Wordpress ever again).

I may have switched to Netlify but it wasn't a case of disliking GitHub Pages! Here are my reasons for switching:

  • More configuration around how the site works:
    • Redirects (already proved their worth!)
    • Also, a simpler config in the form of netlify.toml
  • Staging / production builds
  • Automatic preview branches for pull requests (great for getting feedback before publishing)
  • Dynamic forms in a static site!

 The Current Setup

Okay, so let's break down the current setup and how it works. I can't see that the core of this is going to change any time soon, because I'm extremely happy with how frictionless it all is.


I configured the default deploy context (through the Netlify UI) with the following:

Deploy Contexts:

  • Production branch: source (this could be switched to master now)
  • Deploy previews: Automatically build deploy previews for all pull requests
  • Branch deploys: Deploy only the production branch

Within my blog source, I also have a netlify.toml file which contains more configuration options. It looks like this:

2 environment = { PHP_VERSION = "7.2" }
4 command = "npm run staging"
5 publish = "build_staging"
8 command="npm run production"
9 publish="build_production"

By default everything will build in the staging environment, but for production builds, I use the production environment.

Build Image Selection:

I'm using Ubuntu Xenial 16.04 (default) because it's the latest build image Netlify has. I'd opt for 18.04 if I could.

Build Hook:

I created a custom build hook which we'll use later to trigger a scheduled automatic deployment.

 Jigsaw Requirements

I want to be able to write ahead of myself and by this, I mean that I want to write a post that's scheduled for a date in the future and have GitHub Actions publish it automatically. To make this happen, I made a couple of small changes to the Jigsaw config files.

Firstly, I needed to update the config.staging.php file so that the baseUrl is set to env('DEPLOY_URL'). This means that when Netlify deploys a branch preview, I can navigate the blog correctly. DEPLOY_URL is an environment variable set by Netlify.

Next, I needed to add a filter to my posts collection in my base config.php array:

1'collections' => [
2 'posts' => [
3 'author' => 'James Brooks',
4 'sort' => '-date',
5 'path' => 'blog/{filename}',
6 'filter' => function ($post) {
7 return true;
8 },
9 ],

This is needed because it appears that Jigsaw does not merge configs together, so we need a dummy filter to override later.

Finally, in the config.production.php config, we override the filter method to check the publish date is in the past:

1'filter' => function ($post) {
2 return Carbon::parse($post->date)->isPast();

And now I'm able to use the date field on any of my posts as the published date.

GitHub Actions

My workflow for publishing is now:

  • Create a branch for each new post whilst I'm drafting it. This means that I can start working on a post anywhere (so long as I have access to GitHub).
  • When I'm done with the post, I add a completed label to the PR. GitHub Actions will then automerge this and deploy it.

This is my ./github/workflows/publish.yml file:

1name: Publish Posts
4 schedule:
5 - cron: "0 8-22 * * *"
8 automerge:
9 runs-on: ubuntu-latest
10 steps:
11 - name: automerge
12 uses: "pascalgn/[email protected]"
13 env:
14 GITHUB_TOKEN: "${{ secrets.GH_TOKEN }}"
15 MERGE_LABELS: "finished"
17 - name: scheduled-deploy
18 if: github.event_name == 'schedule'
19 uses: wei/[email protected]
20 with:
21 args: -X POST -d {} "${{ secrets.NETLIFY_BUILD_HOOK }}"

For this to work, you need to create a new secret in your repository for GH_TOKEN, which is a personal access token with repo permissions. I also created a secret of NETLIFY_BUILD_HOOK which contains the URL that Netlify generated for us earlier.

GitHub Actions will automatically run the workflow every hour between 8AM and 10PM (which is typically when I'd want to write a post)! Since any changes I make to the source branch will automatically be deployed, this covers everything I need! By doing this, Netlify is essentially regenerating any draft posts every hour.

I'm particularly happy with this configuration for a few reasons:

  1. I can adjust the schedule as I see fit and run automerge more or less frequently if I need.
  2. I can treat pull requests as drafts until it has the finished label.
  3. Any posts that are merged, but we're not yet at their publish date will automatically build and become published with no manual deployments needed.

Let me know if you use this technique or something similar at @jbrooksuk.