Deploy to GitHub Pages using Actions
Custom Actions workflow for Jekyll and GitHub Pages that actually works.
Context
A GitHub Page site can be set up for either one of the following scenario:
- a repository named «user».github.io containing only the site itself in the main
- a repository containing a project and gh-pages branch for the site
The notes below apply to the former case only, which I refer to as stand-alone site. In this case GitHub by default builds and deploy the Jekyll site every time you push new commits to the repo.
This approach works fine for the majority of the cases especially when using one of the GitHub Pages supported themes and whitelisted plugins. However, this list is pretty slim compared for example to the whole rubygems.org and if your site uses a plugin not included you can’t use the default GitHub deploy method.
If this is the case you’re left with two options, both of which rely on custom GitHub Actions workflows:
- build the static site on your local machine, push the files to the remote (usually inside _site folder) and then use GitHub Actions only to publish it
- create an end-to-end GitHub Actions workflow to automatically build and deploy the site for you on remote
Going forward I analyze the end-to-end method (for a “standalone” site) since it is the most similar to the default deployment with advantage of not being limited to whitelisted plugins (i.e. any plugin from any supported source, even own repos, are allowed).
NOTE - Since August 2022 the very own GitHub Pages deployment framework is based upon GitHub Actions.
CAUTION - Many of the articles I found online refer to ‘gh-pages’ branch without providing too much details on the context. As discussed above this is a very specific scenario of project and site contained in (different branches of) the same repository. This scenario might require a specialized workflow NOT DESCRIBED HERE.
Configure the use of Actions
The build and deploy method can be changed to ‘GitHub Actions’ in the repository Settings > Pages > Build and Deploy settings.

Starter workflows
GitHub Actions provides a set of starter workflows to be used as a base to craft your own. The workflow I picked has a basis is jekyll.yml
# Sample workflow for building and deploying a Jekyll site to GitHub Pages
name: Deploy Jekyll site to Pages
on:
  # Runs on pushes targeting the default branch
  push:
    branches: [$default-branch]
  # Allows you to run this workflow manually from the Actions tab
  workflow_dispatch:
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
  contents: read
  pages: write
  id-token: write
# Allow one concurrent deployment
concurrency:
  group: "pages"
  cancel-in-progress: true
jobs:
  # Build job
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v3
      - name: Setup Ruby
        uses: ruby/setup-ruby@0a29871fe2b0200a17a4497bae54fe5df0d973aa # v1.115.3
        with:
          ruby-version: '3.0' # Not needed with a .ruby-version file
          bundler-cache: true # runs 'bundle install' and caches installed gems automatically
          cache-version: 0 # Increment this number if you need to re-download cached gems
      - name: Setup Pages
        id: pages
        uses: actions/configure-pages@v2
      - name: Build with Jekyll
        # Outputs to the './_site' directory by default
        run: bundle exec jekyll build --baseurl "$"
        env:
          JEKYLL_ENV: production
      - name: Upload artifact
        # Automatically uploads an artifact from the './_site' directory by default
        uses: actions/upload-pages-artifact@v1
  # Deployment job
  deploy:
    environment:
      name: github-pages
      url: $
    runs-on: ubuntu-latest
    needs: build
    steps:
      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v1
Fixes
The Jekyll starter workflow did not work out of the box for me. Here are the changes I made.
Branch to use
The starter workflow uses the ‘default branch’ variable to listen to pushes. That didn’t work for me so I hardcoded the name of the branch to listen to
on:
  push:
    branches: ['main']
Workflow permissions
I adjusted the GITHUB_TOKEN permissions removing ‘content: read’
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
  pages: write
  id-token: write
Update _config.yml
Fine tuning the jekyll config file is possibly the most important step of the process. Running my custom workflow I stumbled upon the ‘invalid date’ issue documented in Jekyll issue #5267
Following the solution in the Jekyll issue #2938 I went on and updated my _config.yml file to exclude ‘vendor’
exclude: 
- vendor
## add here other paths to exclude
Other references
See also the following links for actions related to GitHub Pages build and deployment:
 
       
      