GitHub Action to Automatically Build Website

Tutorial
A tutorial of how to create GitHub Action to automatically build your website.
Author

Pingfan Hu

Published

April 12, 2025

My Use Case & Motivation

This is for my personal documentation of how to create a GitHub Action to automatically build my website. If it benefits you that’ll be great!

In my case, I render my website using Quarto and have it hosted on Netlify. I want to automate the process of building the website whenever I push changes to my GitHub repository.

Netlify has a basic walk-through of website deployment upon GitHub push, which should solve the problem in most cases. I also documented my version of tutorial. However, it requires to fully construct the website on user’s local machine and push the built folder (usually the _site/ folder) to the repository. To do this, I need to always fully rebuild all website pages locally anytime I make changes, and the _site/ folder grows larger and larger over time.

Then I’m thinking of a solution of auto-building the website on GitHub upon push, and ignore the built folder in the repository. This tutorial documents my solution for my own record, and may also benefit you if you have similar needs.

Add Built Folder to .gitignore

The built folder is by default _site/ for Quarto. The first step is to add _site/ to your .gitignore file so it’s no longer tracked by Git.

Create a GitHub Action Workflow

Then, create a GitHub Actions workflow file to build your site when you push to your repository. Create a file at .github/workflows/build.yml with content like this:

name: Build Quarto Website

on:
  push:
    branches: [ main ]
  workflow_dispatch:

jobs:
  build:
    runs-on: ubuntu-latest
    
    steps:
    - uses: actions/checkout@v3
    
    - name: Set up R
      uses: r-lib/actions/setup-r@v2
      
    - name: Install system dependencies
      run: |
        sudo apt-get update
        sudo apt-get install -y libfontconfig1-dev libfreetype6-dev libpng-dev libtiff5-dev libjpeg-dev
      
    - name: Install quarto
      uses: quarto-dev/quarto-actions/setup@v2
      
    - name: Set up R dependencies with renv
      uses: r-lib/actions/setup-renv@v2
      
    - name: Render Quarto website
      run: |
        quarto render
        
    - name: Deploy to Netlify
      uses: nwtgck/actions-netlify@v2.0
      with:
        publish-dir: './_site'
        production-branch: main
        github-token: ${{ secrets.GITHUB_TOKEN }}
        deploy-message: "Deploy from GitHub Actions"
      env:
        NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
        NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}

Set Up Secrets in GitHub

Note

NETLIFY_AUTH_TOKEN and NETLIFY_SITE_ID different:

  1. NETLIFY_AUTH_TOKEN is specific to your Netlify account, so usually you’ll only need one token.
  2. NETLIFY_SITE_ID is specific to each site you deploy, so if you have multiple sites, you’ll need to set up the corresponding NETLIFY_SITE_ID for each site.

Let’s set up NETLIFY_AUTH_TOKEN and NETLIFY_SITE_ID as secrets in the GitHub repository settings.

The NETLIFY_AUTH_TOKEN can be generated from your Netlify account settings:

  1. Log in to Netlify.
  2. At the bottom left corner, click on your profile icon and select “User settings”.
  3. In the “Applications” tab, click on the “OAuth” seciton.
  4. Click on “New access token” to generate a new token.
  5. Copy the generated token and save it in a secure place, since you won’t be able to see it again.

The NETLIFY_SITE_ID can be found in the settings of your Netlify site:

  1. Log in to Netlify.
  2. Select your site from the dashboard.
  3. Go to “Site Configuration”.
  4. Under “General” -> “Site details”, you will find the “Site ID”.

With these two secrets in hand, you can pass them to your GitHub repository:

  1. Go to your GitHub repository.
  2. Click on “Settings” in the repository menu.
  3. In the left sidebar, click on “Secrets and variables” -> “Actions”.
  4. Click on “New repository secret”.
  5. Add NETLIFY_AUTH_TOKEN and paste the token you generated.
  6. Add NETLIFY_SITE_ID and paste the Site ID you found.

Change Netlify Settings for Site Deployment

Since we are deploying with GitHub, we don’t need Netlify to build the site anymore. Here is how to modify it:

  1. Log in to Netlify.
  2. Select your site from the dashboard.
  3. Go to “Site Configuration”.
  4. Under “Build & deploy” -> “Continuous Deployment” -> “Build settings”, click on “Configure”.
  5. Set “Build status” to “Stopped builds”.

Using renv for R Package Dependencies

There are 2 ways to manage R package dependencies in your GitHub Actions workflow. One is to manually install all required packages, and the other is to use renv to manage the dependencies. I chose to use renv so I don’t need to manually update the package list in the workflow file.

You may have noticed that in the build.yml file, I have these under the build jobs:

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

    steps:
    - name: Set up R dependencies with renv
      uses: r-lib/actions/setup-renv@v2

This is to set up the R package dependencies using renv.

Locaclly in your R console, run these to install and initialize renv:

# Install renv if you don't have it
install.packages("renv")

# Initialize renv for your project
renv::init()

# After you've used all the packages in your project
renv::snapshot()

When you run renv::init(), it will create several files including:

  • renv.lock: the package lockfile
  • .Rprofile: hidden, to activate renv when you open the project
  • renv/ directory: contains project-specific package cache

The important file for GitHub Actions is renv.lock, which contains information about all the packages your project needs. This file should be committed to your Git repository.

Two extra steps:

Firstly, in the future, any time you install new packages, you should locally run renv::snapshot() again to let GitHub Actions intall the same packages automatically:

# Update the lockfile with new packages
renv::snapshot()

Another important step is when you switch to another computer or environment. You should run renv::restore() to restore all packages from the lockfile:

# Restore all packages from the lockfile
renv::restore()

Conclusion

Now we are done. The site is still hosted on Netlify, but the building process is fully automated with GitHub Actions. Whenever you push changes to your GitHub repository, the site will be automatically built and deployed to Netlify. There is no need to push _site/ directory or manually rebuild the site locally.