Subscribe to receive notifications of new posts:

A Full CI/CD Pipeline for Workers with Travis CI

2019-03-22

2 min read

In today’s post we’re going to talk about building a CI/CD pipeline for Cloudflare Worker’s using Travis CI. If you aren’t yet aware, Cloudflare Workers allow you to run Javascript in all 165 of our data centers, and they deploy globally in about 30 seconds. Learn more here.

There are a few steps before we get started. We need to have a Worker script we want to deploy, some optional unit tests for the script, a serverless.yml  file to deploy via the Serverless Framework, a .gitignore file to ignore the node_modules folder, and finally, a .travis.yml configuration file. All of these files will live in the same GitHub repository, which should have a final layout like:

----- worker.js
----- serverless.yml
----- test
      . worker-test.js
----- node_modules
----- package.json
----- package-lock.json
----- .travis.yml
----- .gitignore

The Worker Script

In a recent post we discussed a method for testing Workers. We’ll reuse this method here to test a really simple Worker script below which simply returns Hello World! in the body of the response. We will name our Worker worker.js.

addEventListener('fetch', event => {
  event.respondWith(handleRequest(event.request))
})
async function handleRequest(request) {
  return new Response('Hello World!')
}

The Test

We will create a single test case following the method discussed unit testing blog post.

before(async function () {
   Object.assign(global, new (require('@dollarshaveclub/cloudworker'))(require('fs').readFileSync('worker.js', ‘utf8’)).context)
})
// replace worker.js here with the name of your worker file
const assert = require('assert')

describe('Worker Test', function() {
    it('Response with a body that says hello', async function () {
    var url = new URL('https://travis.example.com')
    var req = new Request(url)
    var res = await handleRequest(req)
    var body = await res.text()
    assert.equal(body, 'Hello World!')
    })
})

Then we’ll update our package.json file to include:

"scripts": {
  "test": "mocha"
}

And install mocha with npm install mocha --save-dev and cloudworker with npm install @dollarshaveclub/cloudworker --save-dev.

serverless.yml

Next, we’ll need a serverless.yml file to deploy the worker. This is a config file which is used by the Serverless Framework to deploy serverless apps to supported providers. We became a provider some time ago, and we will use the framework to deploy our Workers in this example.

We will run the sls deploy command in our Travis config and it will pick up our serverless.yml to deploy the Worker for us. serverless.yml will reference ENV variables which we will pass to Travis in the final section of the post.

NOTE: You can deploy with any arbitrary script. We’re using the Serverless Framework in this example because we already integrate with them and getting started is straightforward.

Our serverless.yml will look like:

service:
  name: travis-example
  
provider:
  name: cloudflare
  
config:
  accountId: ${env:CLOUDFLARE_ACCOUNT_ID}
  zoneId: ${env:CLOUDFLARE_ZONE_ID}
  
plugins:
  - serverless-cloudflare-workers
  
functions:
  deploy-from-travis:
    name: travis-deployed-worker
    script: worker

Make sure to install both the Serverless Framework, and the Cloudflare Workers plugin with npm install --save serverless and npm install --save serverless-cloudflare-workers.

travis.yml

Below you’ll see the final .travis.yml and we’ll walk through each piece of it.

language: node_js
node_js:
  - "node"
  
deploy:
  - provider: script
  script: sls deploy
  skip_cleanup: true
  on:
    branch: main

Before diving in, Travis has some great resources on deploying node.js projects here. While this isn’t strictly what we’re doing, it’s a great jumping off point.

So what does this .travis.yml mean? First, we’re telling Travis CI to use the most recent node.js image (you have the option to specify). Then we specify the command to run to actually do the deployment, sls deploy, but only when the main branch is involved in the build. Travis will run npm test for us as it’s default for any node.js project, which will execute our unit tests.

The skip_cleanup: true prevents any conflicts with git during the test and deploy process.

Configuring Travis

Finally! We’re almost there. Setting up Travis CI is really simple. Once you’ve got your account created, make sure your authorize Travis to access the repo which contains the worker, your tests, .travis.yml, and your .serverless.yml.

Next up is adding environmental variables to the build. In this case it’s going to be our CLOUDFLARE_AUTH_EMAIL and CLOUDFLARE_AUTH_KEY values which Serverless picks up to auth API requests.

I also add CLOUDFLARE_ACCOUNT_ID and CLOUDFLARE_ZONE_ID as we referenced them in serverless.yml. Finally I set SLS_DEBUG=*, just to catch any issues from Serverless.

You can add these ENV variables in a variety of ways outlined here. In this example we’re going to add them directly in the Travis UI so they don’t show up anywhere in the repo (as some of them are sensitive).

Navigate to the repo in the Travis UI, and hit the ‘more options’ dropdown to add ENV variables.

Complete!

Now PRs will trigger a test build, and a merge to main a test build and a deployment! Go ahead and test it out.

And that’s it! Did you find this useful? Please let us know if we can make this tutorial better. Thanks.

Cloudflare's connectivity cloud protects entire corporate networks, helps customers build Internet-scale applications efficiently, accelerates any website or Internet application, wards off DDoS attacks, keeps hackers at bay, and can help you on your journey to Zero Trust.

Visit 1.1.1.1 from any device to get started with our free app that makes your Internet faster and safer.

To learn more about our mission to help build a better Internet, start here. If you're looking for a new career direction, check out our open positions.
Cloudflare WorkersServerlessJavaScriptDevelopersDeveloper Platform

Follow on X

Cloudflare|@cloudflare

Related posts