How I started deploying my jekyll blog with Github Actions in 15 minutes
This week I decided to take a look at Github Actions, and found out that the free tier includes 2k minutes of free build time.
In the past I deployed this jekyll blog by triggering some commands with a pre-push
git hook. My blog is hosted in cloudfront and deploying it is as simple as running a s3 cp
command with awscli
.
#!/bin/bash
# deploy
if [[ -n $AWS_ACCESS_KEY_ID ]] && [[ -n $AWS_SECRET_ACCESS_KEY ]]; then
cd site
bundle exec jekyll build
aws s3 cp _site/ s3://dimmaski/ --recursive
echo "Finished deploy"
exit 0
else
echo "AWS creds not set."
exit 1
fi
I had the following git hook.
# .git/hooks/pre-push
protected_branch='master'
current_branch=$(git symbolic-ref HEAD | sed -e 's,.*/\(.*\),\1,')
if [ $protected_branch = $current_branch ]; then
./deploy
exit $?
else
exit 0
fi
In case you are not familiar with git hooks, they are pretty straight forward. You tie a script (e.g a series of commands) to a given git action, pre-push
pre-commit
, etc. (ls .git/hooks
to find all the triggers). Git hooks got me going initially, but it’s not the best option since it forces me to load my AWS credentials into my running shell every time I want to commit, plus it makes it annoying if I want to write a post in another machine. So I found the right alternative that is working for me, at least for now.
Github Actions
What you got here for. Github allows you to define a yaml
file that lives inside your repo and contains all the steps necessary to build and deploy your app. You can find lots of plugins in the marketplace. To achieve the purpose of this post I only needed to look for one specific action: jakejarvis/s3-sync-action
. Since I decided to run my build
step inside a docker container.
name: Jekyll site CI
on:
push:
branches: [ master ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Build the site in the jekyll/builder container
run: |
docker run \
-v ${{ github.workspace }}/site:/srv/jekyll -v ${{ github.workspace }}/_site:/srv/jekyll/_site \
jekyll/builder:latest /bin/bash -c "chmod 777 /srv/jekyll && jekyll build --future"
- uses: jakejarvis/s3-sync-action@master
name: push site to s3 bucket
with:
args: --follow-symlinks --delete
env:
AWS_S3_BUCKET: 'dimmaski'
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_REGION: 'us-west-1'
SOURCE_DIR: '_site'
The CI/CD workflow, if we can even call it that, for a jekyll site deployed in s3 is quite straight forward. Even more when described in yaml
. The only tricky part is that two-line docker run
command, that looks horrendous, but is doing its job. We are setting two volumes: ${{ github.workspace }}/site
mounts our repo inside the container; and ${{ github.workspace }}/_site
allows us to retrieve our static files generated inside the container back to our workspace. (Note that I have a folder called site
in my repository where my jekyll files live. If you’re hosting your files in the root of your repo you should only specify ${{ github.workspace }}
). The deploy step is encapsulated in the jakejarvis/s3-sync-action
. The secrets live inside the repository settings. Go to Settins > Secrets > Add a new secret
.
That’s it. Simple!