Skip to main content

2020 Website Refresh: More Automation Edition

·3 mins

It’s been over 10 months since my last blog post on here, and I decided it was high time for a fresh look at the site. Not to mention I’m on lockdown because of COVID-19. It seemed like as good a time as any to do some spring cleaning both in real life, and online.

Minor Visual Updates #

I decided to make some tiny updates to the site style, most notably a new font for headings.

New heading font: Merriweather

Next I also made a few tiny changes to the background color, and the drop shadow around each blog post. The colour changes are barely perceptible, but it made me happy to make it into a gradient instead of a flat gray.

New drop shadow, new gradient, new circle picture

Lastly, I also changed the header. The home page has a big circular picture of my ugly mug, and some more classy typography. Single post pages have a tiny circle and still, classy typography just moved over to the right.

Classy typography and small circle

Deployment Pipeline #

This is where the real action is.

This site is powered by the Hugo static site generator, and for the longest time, it had been built by a Jenkins job running on my home server which I would manually trigger. Jenkins would dutifully build the site using hugo, upload the generated HTML to Amazon S3, and then create a cache invalidation in AWS CloudFront to bust caches at POPs around the world.

After recently “redoing” my server (post on that coming “soon”) I never recreated poor Jenkins’ docker container and so if I had made any updates to the site in the meanwhile, I would have had to build and deploy the site from my laptop like a savage.

Enter Bitbucket Pipelines #

Disclaimer: I work at Atlassian, but not on the Bitbucket team :)

I already host my website’s git repo on Bitbucket so why not give pipelines a whirl? It had been a long time since I had tried to use Pipelines and they’ve really drastically improved pretty much everything about it.

Here is the bitbucket-pipelines.yml for this website:

image: phybros/docker-hugo-builder:0.67.1

pipelines:
  branches:
    master:
      - step:
          name: Build and minify files
          script:
            - hugo --config willwarren.com.toml
            - minify -r -o public/ public/
          artifacts:
            - public/**

      - step:
          name: Deploy to S3
          deployment: Production
          script:
            - pipe: atlassian/aws-s3-deploy:0.4.1
              variables:
                AWS_DEFAULT_REGION: 'us-east-1'
                S3_BUCKET: 'willwarren.com'
                LOCAL_PATH: 'public/'
            - pipe: atlassian/aws-cloudfront-invalidate:0.3.1
              variables:
                AWS_DEFAULT_REGION: 'us-east-1'
                DISTRIBUTION_ID: 'EXXXXXXXXXXXA'
                PATHS: '/*'

The heavy lifting here is done by Bitbucket’s “pipes” - little reusable stages that are open source. You can see them all here: https://bitbucket.org/product/features/pipelines/integrations.

There is one that basically does an aws s3 sync operation (atlassian/aws-s3-deploy:0.4.1), and another that does aws cloudformation create-invalidation (atlassian/aws-cloudfront-invalidate:0.3.1). These reusable bits are so simple but really powerful when you start connecting them all together.

To make the above work you need to add 2 repository variables AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY. You can do this by going to Settings > Pipelines > Repository Variables. Don’t forget to check the Secured checkbox when adding the variables.

Adding repository variables

That’s it! Now whenever I push to master the pipeline is triggered. It looks something like this:

Running the pipeline

Now the only thing standing in the way of publishing more is writing more!

Manual Deploys #

If you add the line trigger: manual under deployment: Production, Bitbucket gives you a neat little button in the Pipeline run screen that you have to click to allow the deployment to proceed. Super cool!

Docker Image for Hugo #

There was many details that I glossed over, but the most glaring is the first line of the yaml file: image: phybros/docker-hugo-builder:0.67.1. I created a new docker image specifically for building Hugo sites in CI/CD pipelines.

You can go check it out here: https://hub.docker.com/r/phybros/docker-hugo-builder. Currently only Hugo v0.67.1 is supported, but that can be easily changed.

Just send me a PR!