Automating Cloudflare Worker Deployments with CodeShip

Codeship BasicCodeship ProDevelopment

Reading Time: 6 minutes

As web developers, we typically have two options for deploying code: we can push our code to a remote server and run it there, or we can package our code as Javascript and run it in the end-user’s web browser. Both options have their tradeoffs, but when I heard about Cloudflare Workers – an innovative edge-based hosting solution – I was really excited to try them out.

Cloudflare is a DNS provider and content delivery network (or CDN). As such, most users set Cloudflare up as a proxy between clients and their web server.

CloudFlare configuration

In a typical request, Cloudflare can resolve SSL certificates, handle DNS resolution, redirect routes, and cache long-lived resources sent from the server (eg: images, stylesheets, and Javascript files). All of these actions are performed in Cloudflare’s distributed network of 152 data centers around the world, so web browsers will get responses back from the node that is closest to them. This can dramatically improve your site’s load time and decrease the number of requests made to your servers.

But what are Cloudflare Workers?

Cloudflare Workers allow you to deploy Javascript code on Cloudflare’s distributed network. This means that you may be able to build certain features without ever touching your servers while still getting the performance and security benefits of server-side Javascript. Some good use cases for this are dynamic image processing, managing authentication, or proxying private APIs.

While Cloudflare Workers are currently somewhat limited, as the trend towards serverless continues to grow, I think we’ll see more and more services like them with huge potential for speeding up websites and lowering hosting costs.

Building a worker

In this tutorial, we’ll see how to build and deploy a simple Cloudflare Worker using Codeship to automatically deploy our code. Before we get started though, it’s important to understand some of the limitations of Cloudflare Workers:

Even with these limitations, there are several open source examples of workers available. For this tutorial, we’ll start from the Cloudlfare Webpack example repository, and end up with a working demo that is automatically deployed via Codeship.

Building the worker locally first, clone or fork this repository. This sample project simply intercepts all requests and shows the current time in the timezone a user specifies using the query string parameter tz. For example, you can see the restults of this worker by going to [https://builds.khughes.me/time-test?tz=America/Chicago][12].

The main logic of the application is handled in ./src/time.js:

import moment from 'moment' 
import 'moment-timezone'

export async function handleRequest(request) { 
     const time = moment(new Date)
     const url = new URL(request.url)

     let timezone = url.searchParams.get("tz")
     if (!timezone) {
        timezone = "America/Los_Angeles"
     }

     return new Response(time.tz(timezone).format())
} 

The project is already set up to use Webpack to build the Javascript and NPM packages into a single file at ./dist/worker.js, so if you want to build and deploy the woker manually, just run the following:

npm install 
npm run build

Then copy ./dist/worker.js to Cloudflare or use their playground to see it in action.

Note: if you’re going to use this worker on your own site, be sure to set up route pattern matching to define the routes your worker will run at.

Writing the deploy script Uploading the worker manually is fine for a simple test, but that’s going to get annoying if we want to make frequent changes or let other developers update the worker. Fortunately, it’s very simple to deploy a worker using Cloudflare’s REST API, so let’s write a script to handle that.

Create a new file in the scripts/ directory called deploy and add the following:

# !/bin/bash

echo "Deploy Started."

# Make the API call and sets a variable with the HTTP response code

response=$(curl -s -o /dev/null -w "%{http_code}" -X PUT "https://api.cloudflare.com/client/v4/zones/$CLOUDFLARE_ZONE_ID/workers/script" -H "X-Auth-Email:$CLOUDFLARE_EMAIL" -H "X-Auth-Key:$CLOUDFLARE_AUTH_KEY" -H "Content-Type:application/javascript" --data-binary "@./dist/worker.js")

# If the response code was 200, the deploy succeeded, otherwise exit with the HTTP response code

if [ 200 -eq $response ]; then echo "Deploy Succeeded." exit 0 else echo "Deploy Failed." exit $response fi;

This bash script uses CURL to upload the build worker.js file to Cloudflare via their API and respond with a success or error in the command line.

Automating deployments

Method 1: CodeShip Basic

If your Cloudflare Worker is really simple and you want to deploy it alone in its own repository, I’d recommend using Codeship Basic. It’s really easy to set up and it takes less configuration. After you push your code to Github or Bitbucket:

  1. Create a new project in Codeship Basic. Link it to your Worker’s repository.
  2. Add your own setup and test commands.
  3. Add the following three environmental variables to Codeship from your Cloudflare account:
  • a. CLOUDFLARE_EMAIL
  • b. CLOUDFLARE_AUTH_KEY
  • c. CLOUDFLARE_ZONE_ID

cloudflare environment variables

  1. Add the following custom script to run when master is updated:
nvm use 8 
npm install 
npm run build 
bash scripts/deploy

cloudflare codeship deployment pipeline

Push to master and make sure your build passes and the Worker is updated. That’s it!

Method 2: CodeShip Pro

While Codeship Basic is the best option for simple projects, you may want to keep your Cloudflare Workers in a shared repository or perform integration tests using other services during your test suite. In that case, Codeship Pro will be your best option. While it takes slightly more configuration to set up, it offers much more flexibility.

  1. Add your project as a new Codeship Pro project and link it to your repository.
  2. Create a Dockerfile in the root directory of your project. This will install your NPM dependencies and build the Worker inside a Docker image:
FROM node:8
WORKDIR /app
COPY . /app RUN npm i --silent
RUN npm run build
  1. Create a .env file, add it to your .gitignore and .dockerignore files, and add the following Cloudflare environmental variables:
CLOUDFLARE_EMAIL=...
CLOUDFLARE_AUTH_KEY=...
CLOUDFLARE_ZONE_ID=...
  1. Encrypt the .env file as .env.encrypted using Jet and your Codeship AES key available in the settings for your application.

  2. Create a codeship-services.yml and codeship-steps.yml file in the root of your project:

# codeship-services.yml
deployer:
  build: .
  encrypted_env_file: .env.encrypted

# codeship-steps.yml

- name: deploy
  tag: pro 
  service:deployer 
  command:bash scripts/deploy

Commit and push your updates to Github and Codeship will automatically build and deploy the updates to your Cloudflare Worker. If you got lost in any of the steps above, check out the pro branch of this repository to see a working example.

codeship pro deployment

Next steps

While the tutorial above illustrates how you can automatically deploy a Cloudflare Worker using Codeship Basic or Codeship Pro, there are still a few things you probably want to set up for a high quality, production-ready project. For example, I’d suggest creating and deploying a staging Worker and running automated unit tests as part of the continuous integration process. If you have your own tips for running Cloudflare Workers or deploying other serverless hosting solutions using Codeship, let me hear about them on Twitter.

Additional resources

Subscribe via Email

Over 60,000 people from companies like Netflix, Apple, Spotify and O'Reilly are reading our articles.
Subscribe to receive a weekly newsletter with articles around Continuous Integration, Docker, and software development best practices.



We promise that we won't spam you. You can unsubscribe any time.

Join the Discussion

Leave us some comments on what you think about this topic or if you like to add something.