2019-12-25

Building Gatsby with GitHub Actions and deploying to Netlify

gatsby, github, actions, netlify, deployment, ci

banner

Image by Web Donut from Pixabay

Netlify introduced build minutes (300 minutes for the free tier, 1000 for the pro account), which limits build time on their site.

Thankfully, Netlify community support has provided a guideline, How can I optimize my Netlify build time?, with many tips.

You can shave off the build time by delegating the build minutes to GitHub Actions by building and deploying directly to Netlify.


Preface

I am writing this while learning about GitHub Actions, so let me know should you find any errors. :)
If you want to know more about GitHub Actions, check out the official GitHub Actions documentation.

Creating a Workflow file

Refer to Configuring a workflow.

Workflow Definition

Below is the complete GitHub workflow in YAML for building a Gatsby site, and deploying to Netlify every 2 hours.

1name: Build and Deploy to Gatsby every two hours2
3on:4  # 1. Trigger the workflow every 2 hours5  schedule:6    - cron: "0 */2 * * *"7
8jobs:9  build:10    # 2. Using the latest Ubuntu image11    runs-on: ubuntu-latest12
13    steps:14      # Check out the current repository code15      - uses: actions/checkout@v116      # 3. https://github.com/actions/setup-node#usage17      - uses: actions/setup-node@v118        with:19          node-version: "12.x"20      - run: npm install21      # This triggers `gatsby build` script in "package.json"22      - run: npm run build23      # 4. Deploy the gatsby build to Netlify24      - uses: netlify/actions/cli@master25        env:26          NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}27          NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}28        with:29          # 5. "gatsby build" creates "public" folder, which is what we are deploying30          args: deploy --dir=public --prod31          secrets: '["NETLIFY_AUTH_TOKEN", "NETLIFY_SITE_ID"]'
  1. cron schedule triggers the workflow every two hours
  2. In the tatest version of Ubuntu image,
  3. NPM packages are installed & built using Node version 12.x.
  4. Then using the official Netlify's GitHub Actions Netlify-CLI, the site is deployed.
  5. Deploy public folder, generated by gatsby build.

Secret Environment Variables

Deploying to Netlify with Netlify CLI requires a personal access token, NETLIFY_AUTH_TOKEN (and an optional site ID, NETLIFY_SITE_ID).

But You should never expose your API keys, ever, period.

Thankfully, GitHub provides a way to create secret environment variables, which you can pass to the workflow definition.

secrets

You now need to declare the environment variables, and pass it to the CLI.

1env:2  NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}3  NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}4with:5  # 5. "gatsby build" creates "public" folder, which is what we are deploying6  args: deploy --dir=public --prod7  secrets: '["NETLIFY_AUTH_TOKEN", "NETLIFY_SITE_ID"]'
  1. args is what's passed to the Netlify CLI,
  2. secrets are the environment variables for Netlify CLI.

Refer to the deploy command on Netlify CLI documentation.

so the configuration above would look like following in command line.

In powershell,

$env:NETLIFY_AUTH_TOKEN='secret'; $env:NETLIFY_SITE_ID='site id'; netlify deploy --dir=public --prod

In bash,

NETLIFY_AUTH_TOKEN='secret' NETLIFY_SITE_ID='site id' && netlify deploy --dir=public --prod

I wasn't aware of an alternative syntax to declare the workflow, and had hard time with passing the secrets.

1workflow "Publish on Netlify" {2  on = "push"3  resolves = ["Publish"]4}5
6action "Publish" {7  uses = "netlify/actions/cli@master"8  args = "deploy --dir=site --functions=functions"9  secrets = ["NETLIFY_AUTH_TOKEN", "NETLIFY_SITE_ID"]10}

GitHub Actions's YAML editor complains that you can't pass an array to the secret, so you need to turn it into a string,

1#       👇 secrets is a string                    👇2secrets: '["NETLIFY_AUTH_TOKEN", "NETLIFY_SITE_ID"]'3# not an array.4secrets: ["NETLIFY_AUTH_TOKEN", "NETLIFY_SITE_ID"]

Workflow Result

After commiting the workflow file, you can see that the Gatsby was built and deployed to Netlify successfully in the log.

secrets

Now the Netlify log shows that it only took 1 second to deploy.

deploy log

Preventing auto-build on Netlify

When your Netlify site is linked to your GitHub repository, any source code commit will trigger a build on Netlify.

But You can't unlink GitHub repository from Netlify UI, to prevent an auto-build (unless you create a new site without linking to a repository first).

So you need to go to Netlify community support and request to unlink your site(s).
As an exmaple here is the request for SHANc, which was handled quickly on X-Mas! (🙂👍)

Here is a comparison between liked and unlinked sites.

linked vs. unlinked sites

Manual Workflow Trigger

There is no way to manually trigger workflows, so I made the workflow to run on code "push" initially before making it run on schedule.

1name: Build and Deploy to Gatsby every hour2
3# https://help.github.com/en/actions/automating-your-workflow-with-github-actions/configuring-a-workflow#triggering-a-workflow-with-events4on:5  schedule:6    - cron: '0 */2 * * *'7# https://help.github.com/en/actions/automating-your-workflow-with-github-actions/events-that-trigger-workflows#example-using-a-single-event8# 👇 To test, uncomment these and comment three lines above.9# on:10#   push:11#     branches:12#       - master13
14jobs:15  build:16    runs-on: ubuntu-latest17    ...

Check out About workflow events for more triggers.


Image by Web Donut from Pixabay