How I Host Static Sites With Automatic Deploy on Green

This site,, is written in markdown and uses the Hugo static site generator. This post walks you through how I set automatic building, testing, and deployment to Firebase hosting.

Project Setup

I assume we’re starting from a working Hugo project. For more on how to set that up, see the Hugo docs.

Testing Setup

I want the site to be Deploy-on-Green (i.e. only if it passes the tests). The CI setup I use is GCP Cloud Build. I develop and debug these tests locally using the local-cloud-build command documented here. The steps I want are:

1. Verify Hugo build succeeds

There’s already a Hugo community build step available, so I use that.

2. Verify all pages are AMP-valid

This blog uses AMP HTML. I use the amphtml-validator Node package to verify all pages are valid. Here’s what the relevant parts of my package.json look like for that:

  "scripts": {
    "test": "amphtml-validator `find public -type f -name '*.html'"
  "devDependencies": {
    "amphtml-validator": "^1.0.23"

3. Deploy to Firebase hosting

There’s a Firebase community build step available as well, so I use that.

CI Setup

Now to put everything together. Here’s the cloudbuild.yaml file I have for the project. The hugo_build and npm_install steps run in parallel to each other. If everything succeeds, the last step deploys to Firebase.

- name: '$PROJECT_ID/hugo'
  args: []
  waitFor: ['-']
  id: hugo_build
- name: node:10.10.0
  entrypoint: 'npm'
  args: ['install']
  id: npm_install
  waitFor: ['-']
- name: node:10.10.0
  entrypoint: 'npm'
  args: ['test']
  waitFor: ['hugo_build', 'npm_install']
- name: '$PROJECT_ID/firebase'
  args: ['deploy']
  secretEnv: ['FIREBASE_TOKEN']
- kmsKeyName: '{kmsKeyName}'

The secret Firebase key is set up as described here.

Then it’s a matter of adding the build trigger and pointing at your cloudbuild.yaml, and you’re done.

Now whenever I push to the master branch with any changes in my site’s directory, it triggers a new build.