(Note) Using gatsby-plugin-s3 with Github Actions

11 May 2020

I was originally using the Gatsby and S3 sync Github actions together. This worked fine bit shifting. Later I discovered that updates were not showing up when browsing on my mobile. A quick Google and I realised there are some HTTP cache headers that Gatsby recommend which I was not applying. The gatsby-plugin-s3 which implements the recommended caching config. So I decided to switch. I didn’t find Github Action examples online so maybe this post will help somebody save time.

I’m using Cloudflare rather than CloudFront and a pre-created S3 bucket which isn’t managed using code (i.e. Terraform, CloudFormation etc.). It seems they have some workarounds for system like TF and CF that maintain state but maybe it’s best to use the AWS CLI to codify bucket creation in this case.

Here are the relevant snipets. You can view it in context in the repo here.

This is a better setup than what I had before. It’s more Gatsby tuned and much faster. The previous workflow took 2-3mins to execute. This one takes less than 1.5mins. And if you are wondering, my caching issue is resolved. Well at least I’m seeing changes from my mobile. I’m yet to test if what should be cached is being cached.

gatsby-config.js fragment

  plugins: [
      resolve: `gatsby-plugin-s3`,
      options: {
          bucketName: process.env.AWS_S3_BUCKET_NAME,
          region: process.env.AWS_REGION,
          protocol: `https`,
          hostname: `janaka.dev`,

package.json fragment

  "scripts": {
    "deploy": "npx -n \"-r dotenv/config\" gatsby-plugin-s3 deploy"

Github Actions workflow


name: Deploy Website to S3 Hosting

    - master

    name: Build & Deploy
    runs-on: ubuntu-latest
      AWS_S3_BUCKET_NAME: ${{ secrets.AWS_S3_BUCKET }}
      AWS_REGION: ${{ secrets.AWS_REGION }}
    - name: Checkout Repo
      uses: actions/checkout@master
    - name: Install dependencies
      run: yarn install --prod --pure-lockfile
    - name: Build Gatsby Site
      run: yarn build
    - name: Deploy to S3 (with sync)
      run: yarn deploy
        AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}

IAM policy

It seems like they haven’t figured out policies for all the combinations. See more details in this GH issue

    "Version": "2012-10-17",
    "Statement": [
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
            "Resource": "*"
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": [
            "Resource": [

Personal notes and thoughts on web technology, software development, and technical product management by Janaka Abeywardhana. On Github, Twitter, and Instagram

© 2020-2022, Built with Gatsby