Automating Blog Deployment with GitHub Actions
March 12, 2021 -Okay! Day 2 of the new blogging platform, and I've solved the automated deployment problem using GitHub Actions.
GitHub Actions to Test Python
I worked on a small Python project a little while ago and wanted to get CI running with as little effort as possible. I'd heard good things about GitHub Actions (my friend Michael Heap is even writing a book about them).
That project's CI issues were solved by following the instructions. I copied the following YAML into .github/worflows/main.yml
and I was more-or-less done.
name: Python package
on: [push]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [2.7, 3.5, 3.6, 3.7, 3.8]
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install flake8 pytest
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
- name: Lint with flake8
run: |
# stop the build if there are Python syntax errors or undefined names
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
- name: Test with pytest
run: |
pytest
Porting the Knowledge to Deployment
What I wanted to do this time was quite similar. I wanted to build the site's static pages, and then, if on the master branch copy the files to my personal server, using SCP.
I found an existing Zola deploy action that builds a Zola site, and then deploys to GitHub Pages, but that wasn't quite what I wanted. Nevertheless, it seemed like a good starting point, so I forked it, and then started hacking on it.
And then I had an epiphany! I already had steps that checked out the code and built it into a static site. All I needed was another small, specific step
to SCP to my server. A quick search on GitHub's Action Marketplace showed up the perfect action, appleboy/scp-action.
So, now I have the following workflow:
name: Build and deploy
on:
push:
branches:
- master
pull_request:
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: 'Checkout'
uses: actions/checkout@master
- name: 'Build only'
uses: shalzz/zola-deploy-action@master
env:
BUILD_ONLY: true
deploy:
if: github.ref == 'refs/heads/master'
needs: build
runs-on: ubuntu-latest
steps:
- name: 'Checkout'
uses: actions/checkout@master
- name: 'Build Site'
uses: shalzz/zola-deploy-action@master
env:
BUILD_ONLY: true
- name: Deploy Site
uses: appleboy/scp-action@master
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.KEY }}
source: "public"
target: "/var/lib/websites/judy.co.uk"
strip_components: 1
It'll build on any push to master, or any new PR. If the commit is to master, then it'll also deploy to my server using SCP. Using a small set of focused actions (Unix philosophy, anyone?) has led me to something much more simple and maintainable than maintaining my own "build and deploy and ..." action.
One thing I've noticed is that it's building the Docker images each time, before spinning up the containers. I haven't found a way to speed things up by getting around this, but if you know, please contact me and let me know!
I have to say that it's nice when a task that shouldn't be hard turns out to not actually be hard. Now I've reduced the friction for publishing to my blog, so if you come here in 2025 and this is the last post then there's nobody else to blame.
I think it's time for a Negroni.