This is a continuation post from Hugo Setup and Deployment in Hugo series.

In the previous post, we covered the basics of using Hugo. Not only the basics, we also learnt behind the scenes of SSG, getting your site published with GitHub Pages, and finally, we wrote a deployment script written in bash which is used to automatically update the blog’s contents.

The last script we wrote actually is not an effective way to deploy our site because it will generate lots of new HTML files on our machine. With this way, instead of uploading only the files we modified, all these files will be uploaded to the Internet every time we update our site. If you care about network bandwidth or things like SSD endurance, that’s probably not a good thing. Luckily, we can solve this with GitHub Actions.

GitHub Actions basically does the same thing as our deployment script, but, instead of using our own machine to generate and push the HTML files, we’ll let GitHub VM orDocker instances do it for us.

In this post, we’ll focus more on the deployment side.

Goals

  • Automate Site Deployment using GitHub Actions
  • Use theme as submodule

Prerequisites

Prerequisites are still the same, they are:

  • A GitHub account
  • Familiarity with CLI
  • Familiarity with Git.

Preparation

Clean Up

Let’s start by reviewing the previous site structure, here’s where we left it:

$ tree -a -L 2 -I "\.git"
.
├── .gitmodules
├── archetypes
│   └── default.md
├── config.yml
├── content
│   └── post
├── data
├── deploy.sh
├── layouts
├── public # <-- All files under this folder are hosted using GitHub Pages,
│   ├── 404.html
│   ├── assets
│   ├── categories
│   ├── en
│   ├── fa
│   ├── fr
│   ├── index.html
│   ├── index.json
│   ├── index.xml
│   ├── page
│   ├── post
│   ├── robots.txt
│   ├── series
│   ├── sitemap.xml
│   └── tags
├── resources
│   └── _gen
├── static
└── themes
    └── PaperMod

20 directories, 10 files

We’ll now ignore the public folder and remove all of its content including the git repository inside it because this will be handled by GitHub Actions later.

$ rm ./public/* -r f
$ rm ./public/.git -rf

If you happen to use the public folder as a submodule, remove the following lines from .git/config and .gitmodules

[submodule "public"]
        url = https://github.com/your-username/my-blog.git
        active = true

Clean any cached content from the public folder.

$ git rm --cached ./public -f

Then let’s create another GitHub repository with the format your-username.github.io, because we’re going to use this repo as the remote repository of our site.

$ git remote add origin https://github.com/your-username/your-username.github.io.git

For the config.yaml, change the baseURL value with:

baseURL: "https://your-username.github.io/"

Add the Theme as Submodule

If you happen to not using theme as submodule previously, this time we will.

Run the following command to add the PaperMod theme we cloned previously as a submodule of our site.

$ git submodule add https://github.com/adityatelange/hugo-PaperMod.git themes/PaperMod

If you don’t use the same theme, simply replace the url and directory parts to match yours.

Configure Github Actions

In the deployment script, we’ve automated several things: site build, commit, and push our site to GitHub. We can call the execution of this script as a workflow that runs a single job, it is to deploy our site. Each command executed within the deployment script (build, commit, push) can be referred as a step.

GitHub Actions are basically the advanced version of the deployment script we created. It’s event-driven, which means we can set a specific event to trigger the workflow. In this case, we’ll create an event that will trigger the site deployment each time we push a new commit to the main branch.

Create the Workflow

A workflow file for GitHub Actions must be written in YAML syntax, and it’s placed under a special directory called .github/workflows/[here].yml, so let’s create the folder first inside our site repository.

$ mkdir -p ./.github/workflows

We’ll save the following codes under the workflow directory with a name gh-pages.yml (./.github/workflows/gh-pages.yml).

name: github pages

# the event
on:
  push:
    branches:
      - main  # Set a branch to deploy

jobs:
  deploy:
    runs-on: ubuntu-18.04
    steps:
      - uses: actions/checkout@v2
        with:
          submodules: true  # Fetch Hugo themes (true OR recursive)
          fetch-depth: 0    # Fetch all history for .GitInfo and .Lastmod

      - name: Setup Hugo
        uses: peaceiris/actions-hugo@v2 
        with:
          hugo-version: 'latest'
          extended: true
        
      - name: Build 
        run: hugo --minify --cleanDestinationDir

      - name: Deploy
        uses: peaceiris/actions-gh-pages@v3
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          publish_dir: ./public

You can study the code yourself, because I’m not the one who created it 😅. But, to make sure that the public folder always get cleaned first before build, I added the --cleanDestinationDir option.

Let’s commit this workflow and push it to GitHub.

$ git add ./.github/workflows/gh-pages.yml
$ git commit -m "Add gh-pages.yml"
$ git push -u origin main

Trigger the Workflow!

We can create a new post, then add some text to it.

$ hugo new post/test-gh-actions.md
$ echo 'Test GH Action' >> content/post/test-gh-actions.md

Finally, commit the change and push it to your repository to trigger the workflow

$ git commit -m "Trigger build"
$ git push -u origin main

To observe the deployment process/workflow, we can navigate to the site repository and click on the Actions menu (https://github.com/your-username/your-username.github.io/actions).

Revisit your site to verify.

Off-Topic

My Current Deployment

My deployment process is a little bit different. This is because I’ve separated my blog into two repositories: blog-core and fahmifj.github.io . The blog-core repo is a private repo that contains all of my site resources in raw. The fahmifj.github.io repo is a public repository that contains all the generated html from the blog-core repo.

I added a GitHub Actions workflow in the blog-core repo. It runs automatically when I update the repo, generates static HTML files, and then pushes them to the public repo. This blog-core repo held my secret token, which GitHub Actions uses to authenticate and make changes to the public repo.

image-20211102111943965

Note: these are not the actual commands.

Well, it’s not in detail, but it should give you an idea of how it works. Visit this site if you want to learn more about it.

See you in another post!

References