loading...
Cover image for Building Gatsby with GitHub Actions and deploying to Netlify

Building Gatsby with GitHub Actions and deploying to Netlify

dance2die profile image Sung M. Kim Originally published at sung.codes on ・4 min read

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.

name: Build and Deploy to Gatsby every two hours

on:
  # 1. Trigger the workflow every 2 hours
  schedule:
    - cron: "0 */2 * * *"

jobs:
  build:
    # 2. Using the latest Ubuntu image
    runs-on: ubuntu-latest

    steps:
      # Check out the current repository code
      - uses: actions/checkout@v1
      # 3. https://github.com/actions/setup-node#usage
      - uses: actions/setup-node@v1
        with:
          node-version: "12.x"
      - run: npm install
      # This triggers `gatsby build` script in "package.json"
      - run: npm run build
      # 4. Deploy the gatsby build to Netlify
      - uses: netlify/actions/cli@master
        env:
          NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
          NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}
        with:
          # 5. "gatsby build" creates "public" folder, which is what we are deploying
          args: deploy --dir=public --prod
          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.

        env:
          NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
          NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}
        with:
          # 5. "gatsby build" creates "public" folder, which is what we are deploying
          args: deploy --dir=public --prod
          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.

workflow "Publish on Netlify" {
  on = "push"
  resolves = ["Publish"]
}

action "Publish" {
  uses = "netlify/actions/cli@master"
  args = "deploy --dir=site --functions=functions"
  secrets = ["NETLIFY_AUTH_TOKEN", "NETLIFY_SITE_ID"]
}

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,

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

Workflow Result

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

log

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.

name: Build and Deploy to Gatsby every hour

# https://help.github.com/en/actions/automating-your-workflow-with-github-actions/configuring-a-workflow#triggering-a-workflow-with-events
on:
  schedule:
    - cron: '0 */2 * * *'
# https://help.github.com/en/actions/automating-your-workflow-with-github-actions/events-that-trigger-workflows#example-using-a-single-event
# 👇 To test, uncomment these and comment three lines above.
# on:
#   push:
#     branches:
#       - master

jobs:
  build:
    runs-on: ubuntu-latest
    ...

Check out About workflow events for more triggers.


Image by Web Donut from Pixabay

Discussion

pic
Editor guide
Collapse
saul profile image
Saul Hardman

Really great breakdown @dance2die 🙇‍♂️ After recently configuring E2E tests to run via GitHub actions I'll now look at deploying the site in the same manner.

Now that I think about it, I'm hoping to be able to run the E2E tests on the Netlify production, branch, and deploy previews themselves – let's hope that's possible!