Social Distancing Part 2 - Adventures in Continuous Integration

It all sounded so simple.1 At least this is what I told myself when I decided to move off of my previous host and on to Netlify. It was going to be great - almost all of the capabilities of a VPS for free, but I didn’t have to manage it.

This kind of setup is more common these days and works well if you want to get a site up and running quickly without having to fiddle with configuring a server.2 In my case, I had this blog on DreamHost and an existing microsite (my Reverse Job Posting) over on GitHub Pages but wanted more control over things like HTTP headers and redirects.

Around that time, I watched John Wilander’s presentation from WWDC 18 and Scott Helme’s from dotSecurity 2016 and thought, ‘I can do this!’

Netlify even has a sandbox environment, called the “Playground” where you can test out rules to make sure they work. Take those rules, export them in a TOML file - Netlify’s format of choice for configuration data - upload it to a domain, and that should be it…

Not quite. Enter Content Security Policy.

In theory, the pitch for CSP is awesome. Security configuration changes that are really only a few key-value pairs. You could argue that this is overkill, that for a single page application (no, not that kind - although I do have a Service Worker) it’s needlessly complicated, but I was too far into “learning mode” to think about that, so I pressed on. Problem is, if you don’t do it correctly, parts of your site will disappear3 and you might not know until it’s live on the Internet.

In the past, this wasn’t an issue for me. I ran make or rake locally, then uploaded the files and that was it. Well, in a CI scenario, that’s a problem. If, for example, I forgot to run the build task or didn’t set CSP to report-only, raw Markdown might get displayed, things wouldn’t show up, or the site would refuse to accept changes in a stylesheet.

It was infuriating.

After many false starts (my repo’s history for this time period is a mess), and sleeping on the problem for a few days, I finally got this working. Long term, this will allow me to investigate how I can use Netlify’s AWS Lambda integration to send off a tweet whenever a new post is published.4

Ambitious to be sure, especially given how much fumbling about I did at the beginning - but now I’m halfway there. That’s a win.


  1. Famous last words.

  2. See also - GitHub Pages, Heroku, and Statically

  3. If you have external scripts from somewhere else, but specify just the default source e.g, ‘self’ - only load scripts from my domain - _no matter what you do_, those other resources will refuse to load. It is possible to list a resource as ‘none’, but not loading any URLs of a given type isn’t all that common.

  4. From what I can tell, deploying via the CI method is a requirement if you want to use functions.