Overview

Like many developers in this day and age I rely on a service provided by GitHub called GitHub Pages to deploy my side projects, experiments and blog. It is free, has custom domain support, and overall works really well for static sites. The only downside is that deploying a page can sometimes be a hassle depending on the code structure. In this article I'll talk about using GitHub Actions to simplify this process. I have also recorded a video if that's more your speed!

In order to better illustrate lets take a basic Angular application and observe its package.json file. Here we have scripts for starting the application locally, and another for compiling the production ready build. When the build script is finished it pushes the contents into a subfolder called build which is what we use on our web server.

package.json
"scripts": {
  "build": "ng build",
  "start": "ng start",
  "test": "ng test",
}

When maintaining a project like this on GitHub you'd usually push your source code to the main branch, ignoring any build artifacts. If you're leveraging GitHub Pages you'd typically have the compiled version of your application sitting on another branch such as docs or gh-pages which is what GitHub Pages would use to serve your application to the masses.

Where this becomes tricky is when you need to actually commit that compiled code. For every change you make to your source code you need to manually commit the compiled code which adds another step to the process, increasing the chance that you may forget to do it. Additionally what if you don't have access to your computer and want to make a quick update on your phone or tablet but you can't re-build your application?

Enter the GitHub Pages Deploy Action

The best thing to do in my opinion is to automate this process using GitHub Actions. GitHub Actions is a CI/CD tool that allows you to trigger a workflow on any event that GitHub Supports. It's very similar to things like CircleCI and Jenkins except it has really great support for this sort of task in the form of community created actions.

To get started simply create a .yml file in the .github/workflows directory, for this we'll call it deploy.yml. The following boilerplate will run a job called Build and Deploy whenever a commit is pushed to the main branch. Once the workflow runs it will use git to checkout the current branch so we can start processing our build.

.github/workflows/deploy.yml
name: Build and Deploy
on:
  push:
    branches:
      - main
jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    concurrency: ci-${{ github.ref }}
    steps:
      - name: Checkout 🛎️
        uses: actions/checkout@v2

Next up we'll need to add a step to compile our production ready build. For this we can add two new steps, one which configures our Node version to ensure it matches our application, followed by another that runs the necessary commands with npm. Depending on how your application is built you may need to add another step between these to install any sort of required environments such as Python or Java.

.github/workflows/deploy.yml
name: Build and Deploy
on:
  push:
    branches:
      - main
jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    concurrency: ci-${{ github.ref }}
    steps:
      - name: Checkout 🛎️
        uses: actions/checkout@v2

      - uses: actions/setup-node@v1
        with:
          node-version: '16.13.2'

      - name: Install and Build 🔧
        run: |
          npm ci
          npm run build

Lastly we need to add a step which will make the deployment for us. For this we can leverage the github-pages-deploy-action action, made by yours truly. In this step you'll need to configure the name of the folder where your compiled code gets pushed into, and then the branch you'd like to push that compiled code to. You can change the branch that GitHub Pages uses by going to your repository settings.

.github/workflows/deploy.yml
name: Build and Deploy
on:
  push:
    branches:
      - main
jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    concurrency: ci-${{ github.ref }}
    steps:
      - name: Checkout 🛎️
        uses: actions/checkout@v2

      - name: Install and Build 🔧 # This example project is built using npm and outputs the result to the 'build' folder. Replace with the commands required to build your project, or remove this step entirely if your site is pre-built.
        run: |
          npm ci
          npm run build

      - name: Deploy 🚀
        uses: JamesIves/github-pages-deploy-action@v4
        with:
          branch: gh-pages # The branch the action should deploy to.
          folder: build # The folder the action should deploy.

Depending on your needs you can configure the deployment step in multiple different ways. If you need to deploy to a different repository you can do that by leveraging the repository-name field, you can even specify a target-folder if you want your production build to deploy to a specific folder within a branch. Take a look at the documentation for more details.

.github/workflows/deploy.yml
- name: Deploy 🚀
  uses: JamesIves/github-pages-deploy-action@v4
  with:
    branch: gh-pages
    folder: build
    repositorty-name: JamesIves/lab
    target-folder: public

Once the workflow has been pushed to your project you'll be able to see the workflow runs by selecting the Actions tab within the GitHub interface. If everything looks good and there's no errors everything will be green and your application will be deployed.

Flow

Keeping it Updated

Like any sort of third party dependency it's always a good idea to keep it updated, and GitHub Actions are no different. Using GitHub's built in Dependabot service you can configure it to make frequent pull requests against your project to update your workflow versions as they become available on the marketplace. To do this you can create a dependabot.yml file within the .github directory and add the following to it.

.github/dependabot.yml
version: 2
updates:
  - package-ecosystem: github-actions
    directory: '/'
    schedule:
      interval: daily
      time: '10:00'
    open-pull-requests-limit: 10

Closing Notes

Around three years ago I created the github-pages-deploy-action project as my first real venture into the world of open source. I built this action so I could make continued updates to a blog while being away from my work laptop. The community response has been fantastic and I'm very happy with how it has evolved over the years as a result. I even had the opportunity to be interviewed by GitHub for my involvement back in 2020 which you can read here.

GitHub Action
Hero

In the three years that I've maintained this project it has seen the following as of January 2022:

If you'd like to check out some of my other projects you can check out the Fetch API Data Action which I wrote an article about a while ago or you can check out this one which I created to simplify the process of adding GitHub Sponsors to the README of popular projects as a perk for donating.

If you have any questions you can drop a note on the discussion board for the project. Happy new year and thank you for reading!