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!