Using GitHub Actions to Publish This Website
September 11, 2022I have recently moved this website from DreamHost to AWS. While I was able to automate the setup of the infrastructure, I was still deploying changes manually. It is not a very cumbersome process and it involves the following steps after a change is created:
- Build the website;
- Sync the new website contents with the main S3 bucket;
- Invalidate the cache of the non-
www
CloudFront distribution; - Invalidate the cache of the
www
CloudFront distribution.
In its essence, this involves running the following 4 commands, in sequence:
This is not terrible to run each time I introduce a new change, but it would be
easier if I could make it so that every push to the master
branch of the
repository which holds the contents of the website would trigger
a deploy. Fortunately we can use GitHub Actions for this.
Setting Up the GitHub Action
In order to set that up, we first need to create a workflow. Workflows live in
the .github/workflows
folder, and that is where I have created the
deploy.yml
file.
We start by giving the workflow a name:
Then, we setup which actions trigger a workflow run. In this case, I want every
push to the master
branch to trigger it:
Following that, we can start defining our job. In this case, we need to specify in which environment the job should run and the list of steps that comprise it. We’re OK with running on the latest Ubuntu version:
To build the website, we need to have 3 steps: (1) checkout the repository, (2)
setup ruby and install dependencies and (3) run bundle exec jekyll build
:
Once the site is built, we need to publish it to S3 and invalidate the caches of the CloudFront distributions. The AWS Command Line Interface is already available in GitHub-hosted virtual environments, so we just need to set up the credentials we want to use. In this case, we want to reference some repository secrets which we will set up later:
With the credentials set up, we can run the commands we previously listed:
The full YAML for the workflow definition is as follows:
Creating a User for GitHub Actions
To set up the credentials this workflow is going to use to interact with AWS, I wanted to create a user with permissions to interact with the relevant S3 bucket and CloudFront distributions only. To do that, I have added the following to the Terraform definition (refer to the previous post for more details on the existing Terraform definition):
This creates a new IAM user, attaches a policy to it that gives it
access to the relevant S3 and CloudFront resources, and creates a new access key
which we will set up as a secret in our GitHub repository. The secret access key
gets stored in the Terraform state, but we define an output that allows us to
read it with terraform output -raw github-actions_aws_iam_access_key_secret
.
With the GitHub secrets appropriately set up, we now have a
workflow that publishes this website whenever a new commit is pushed to the
master
branch.