Deploying GitHub Pages sites with GitHub Workflows
Tags: github, githubpages, githubworkflows, githubactions
Published: 2023-03-20 17:32:53

---
title: Deploying GitHub Pages sites with GitHub Workflows
published: true
description: Take more control over how your GitHub Pages sites are deployed.
tags: github, githubpages, githubworkflows, githubactions
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5s6zws72lmb75hq8vtl8.png
---

I've written before about [how I use GitHub Workflows to keep "semi-static" web sites up to date](https://dev.to/davorg/github-actions-for-semi-static-web-sites-597g). It's a technique that I've found really useful. When I wrote that blog post, things were pretty simple - you chose which branch held your web site (there was a tradition for a while to use `gh-pages`) and whether the web site pages were in the repos root directory or the directory called `/docs`. I usually put my web site files into the `/docs` directory in the `master` (now `main`) branch and things worked just fine.

The reason for storing the site in `/docs` was so that there was a separation between the files that were used to generate the site from the generated output site itself. Many of my repos would have a `/tt` directory that contained templates, a `/data` directory which contains JSON files or an SQLite database and a `/bin` directory with a `build` program that pulls all that stuff together and generates a pile of HTML files that end up in the `/docs` directory. In my original blog post on this subject, I demonstrated a GitHub Workflow definition that would regenerate the site (when input files changed or on a schedule) and committed any changed files in the `/docs` directory. Some GitHub magic would then ensure that the new version of the site was deployed to the GitHub Pages server. All was well with the world.

Then, a few months ago, things got a little more complicated. We gained options about how your GitHub Pages site was deployed. The standard version that I'd be using before was called "deploy from a branch" but there was another option called "GitHub Actions". It seemed likely to me that I really needed to start using the "GitHub Actions" option, but things were still working the old way, and I had far more interesting things to investigate, so I left things the way they were.

Well, I say things were still working in the old way... They were, but something was a bit different. It seemed that the old method was being powered by a new GitHub Workflow called "pages-build-deployment" that had been automatically added to all the repos that needed it. And looking into the details of that workflow, I noticed that it was doing some things that were unnecessary in my repos - for example it assumed that the site was being built using [Jekyll](https://jekyllrb.com/) and that was only true for a couple of my repos. For most of them, that was unnecessary work. So I needed to look into the new deployment option in more detail.

I started a couple of weeks ago, by simply switching the option from "deploy from a branch" to "GitHub Actions" in the hope that, because I was already using GitHub Actions, things would Just Work. But, unfortunately, that wasn't the case. My new site was being generated and committed to the repo - but the changes weren't showing up on the live site. So I switched things back until I had time to look into in it more detail.

That time was today. It seemed that I needed to include code in my GitHub Workflow that would actually handle the deployment of the site to the GitHub Pages servers. A quick search of the [GitHub Actions marketplace](https://github.com/marketplace?type=actions) found the [Deploy GitHub Pages site](https://github.com/marketplace/actions/deploy-github-pages-site) action which seemed to be the right thing. But reading the documentation, I worked out that it wanted to deploy the site from an artifact, so I needed to create that first. And then I found [Upload GitHub Pages artifact](https://github.com/marketplace/actions/upload-github-pages-artifact) which did the right thing. So it was just a case of adding these two actions to my workflows in the correct way.

Previously, my workflows for these sites just needed a single job (called `build`) but now I added a `deploy` job which depended on `build`. For example, the workflow that builds [Planet Perl](https://perl.theplanetarium.org/) now looks like this:

    name: Generate web page

    on:
      push:
        branches: '*'
      schedule:
        - cron: '37 */4 * * *'
      workflow_dispatch:

    jobs:
      build:
        runs-on: ubuntu-latest
        container: davorg/perl-perlanet:latest

        steps:
        - name: Checkout
          uses: actions/checkout@v3

        - name: Create pages
          run: |
            mkdir -p docs
            perlanet > perlanet.log 2>&1
        - name: Commit new page
          if: github.repository == 'davorg/planetperl'
          run: |
            git config --global --add safe.directory /__w/planetperl/planetperl
            GIT_STATUS=$(git status --porcelain)
            echo $GIT_STATUS
            git config user.name github-actions[bot]
            git config user.email 41898282+github-actions[bot]@users.noreply.github.com
            git add docs/
            if [ "$GIT_STATUS" != "" ]; then git commit -m "Automated Web page generation"; fi
            if [ "$GIT_STATUS" != "" ]; then git push; fi
        - name: Archive perlanet logs
          uses: actions/upload-artifact@v3
          with:
            name: perlanet.log
            path: ./perlanet.log
            retention-days: 3

        - name: Update pages artifact
          uses: actions/upload-pages-artifact@v1
          with:
            path: docs/

      deploy:
        needs: build
        permissions:
          pages: write
          id-token: write
        environment:
          name: github-pages
          url: ${\{ steps.deployment.outputs.page_url }}
        runs-on: ubuntu-latest
        steps:
        - name: Deploy to GitHub Pages
          id: deployment
          uses: actions/deploy-pages@v1

The bits that I've added are the final step in the `build` job ("Update pages artifact") and the new `deploy` job. All of the code is largely copied from the documentation of the two actions I mentioned above.

Having made this changes to one of my planet sites, I switched the deployment method and forced the workflow to run. And was very happy to see it ran successfully and the new version of the site appeared at the live URL as soon as the deployment had changed.

This makes me happy as I feel I'm using the GitHub Pages deployment the way that they're supposed to be used. I've updated all of my [planet sites](https://theplanetarium.org/) to use this method, but I have several other sites that I'll need to get round to switching at some point.

As always when I find out something new about a GitHub feature, it leaves me with a couple of other suggestions for improvements:

* It's possible to [call one workflow from another](https://docs.github.com/en/actions/using-workflows/reusing-workflows). The planet workflows are all very similar. I wonder if I can define a single workflow that does all of the work and just call that from the individual workflow definition - passing in parameters to handle the differences.
* Now I'm deploying the sites from artifacts, there is no need for the generated site to actually exist in the repo. That might well make a few things quite a bit easier.

Anyway, I thought I'd share what I had discovered today. Is anyone else generating web sites this way? How do you do it?