Skip to content
Workers
Visit Workers on GitHub
Set theme to dark (⇧+D)

GitHub SMS notifications using Twilio

Before you start

All of the tutorials assume you have already completed the Get started guide, which gets you set up with a Cloudflare Workers account, and the Workers CLI tool, Wrangler.

Overview

In this tutorial, you will learn to build an SMS notification system on Workers to receive updates on a GitHub repository. Your Worker will send you a text update using Twilio when there is new activity on your repository.

You will learn how to:

  • Build Webhooks using Workers
  • Integrate Workers with GitHub and Twilio
  • Use Worker secrets with Wrangler

Video of receiving a text after pushing to a repo


Generate a project

Start by using wrangler generate to create a Worker project in the command line:

Generate a project
$ wrangler generate github-twilio-notifications
$ cd github-twilio-notifications

Inside of your new github-sms-notifications directory, index.js represents the entry point to your Cloudflare Workers application. You will configure this file for most of the tutorial.

You will also need a GitHub account and a repository for this tutorial. If you do not have either setup, create a new GitHub account and create a new repository to continue with this tutorial.

First, create a Webhook for your repository to post updates to your Worker. Inside of your Worker, you will then parse the updates. Finally, you will send a POST request to Twilio to send a text message to you.

You can reference the finished code on this GitHub repository.


Configure GitHub

To start, you will need to configure a GitHub Webhook to post to your Worker when there is an update to the repository:

  1. Go to your Github repository's Settings > Webhooks > Add webhook.

  2. Set the Payload URL to the /webhook path on your Worker URL. You can find your worker URL by populating your account id in the wrangler.toml file and then running wrangler publish in your command line to generate a live URL for your Worker.

  3. In the Content type dropdown, select application/json.

  4. In the Secret field, input a secret key of your choice.

  5. In Which events would you like to trigger this webhook?, select Let me select individual events. Select the events you want to get notifications for (such as Pull requests, Pushes, and Branch or tag creation).

  6. Select Add webhook to finish configuration.

GitHub config screenshot


Parsing the response

With your local environment set up, you will now parse the repository update with your Worker. If you experience any difficulty, refer to the finished index.js.

Your generated index.js should look like this below:

index.js
addEventListener("fetch", event => {
event.respondWith(handleRequest(event.request))
})
/**
* Respond with hello worker text
* @param {Request} request
*/
async function handleRequest(request) {
return new Response("Hello worker!", {
headers: { "content-type": "text/plain" },
})
}

Begin by modifying the starter code to handle a POST response and renaming the request handler. You can use the request.method property of request to check if the request is a POST request, and send an error response if the request is not a POST request. The simpleResponse function is an easy wrapper for you to respond with requests using your Worker.

index.js
function simpleResponse(statusCode, message) {
let resp = {
message: message,
status: statusCode
}
return new Response(JSON.stringify(resp), {
headers: { "Content-Type": "application/json" },
status: statusCode
})
}
addEventListener("fetch", event => {
event.respondWith(githubWebhookHandler(event.request))
})
async function githubWebhookHandler(request) {
if (request.method !== "POST") {
return simpleResponse(
200,
"Please send a POST request :)"
)
}
}

Next, you will validate that the request is sent with the right secret key. GitHub attaches a hash signature for each payload using the secret key. You can use a helper function called checkSignature on the request to ensure the hash is correct. Then, you can access data from the Webhook by parsing the request as JSON.

index.js - githubWebhookHandler()
async function githubWebhookHandler(request) {
if (request.method !== "POST") {
return simpleResponse(
200,
"Please send a POST request :)"
)
}
try {
const formData = await request.json()
const headers = await request.headers
const action = headers.get("X-GitHub-Event")
const repo_name = formData.repository.full_name
const sender_name = formData.sender.login
if (!checkSignature(formData, headers)) {
return simpleResponse(403, "Wrong password, try again :P")
}
} catch (e) {
return simpleResponse(
200,
`Error: ${e}`
)
}
}

The checkSignature function will use the crypto library to hash the received payload with your known secret key to ensure it matches the request hash. GitHub uses an HMAC hexdigest to compute the hash in the sha1 format.

index.js
const crypto = require("crypto")
async function createHexSignature(requestBody) {
let hmac = crypto.createHmac("sha1", SECRET_TOKEN)
hmac.update(requestBody,"utf-8")
return hmac.digest("hex")
}
async function checkSignature(formData, headers) {
let expectedSignature = await createHexSignature(formData)
let actualSignature = headers.get("X-Hub-Signature")
return expectedSignature === actualSignature
}

Since our project relies on importing a library, use webpack and update your wrangler.toml file to set type = "webpack".

Your wrangler.toml should look something like this:

wrangler.toml
name = "nameless-bonus-1fdf"
type = "webpack"
account_id = "xxxxxxxxx"
workers_dev = true
route = ""
zone_id = ""

Sending a text with Twilio

Finally, you will send a text message to you about your repository activity using Twilio. You will need a Twilio account and a phone number that can receive text messages. Refer to the Twilio guide to get set up. (If you are new to Twilio, they have an interactive game where you can learn how to use their platform and get some free credits for beginners to the service.)

You can then create a helper function to send text messages by sending a POST request to the Twilio API endpoint. Refer to the Twilio reference to learn more about this endpoint.

You construct your headers and body in the format shown in the Twilio reference page. Change the from value to your Twilio phone number.

index.js - sendText()
async function sendText(message){
const endpoint = "https://api.twilio.com/2010-04-01/Accounts/" + ACCOUNT_SID + "/Messages.json"
let encoded = new URLSearchParams()
encoded.append("To", RECIPIENT)
encoded.append("From", "+19388887573")
encoded.append("Body", message)
let token = btoa(ACCOUNT_SID + ":" + AUTH_TOKEN)
const request = {
body: encoded,
method: "POST",
headers: {
"Authorization": `Basic ${token}`,
"Content-Type": "application/x-www-form-urlencoded"
}
}
let result = await fetch(endpoint, request)
result = await result.json()
return new Response(JSON.stringify(result), request)
}

To make this work, you need to set some secrets to hide your ACCOUNT_SID and AUTH_TOKEN from the source code. You can set secrets with wrangler secret put in your command line.

$ wrangler secret put ACCOUNT_SID

Use wrangler to set your Twilio ACCOUNT_SID, RECIPIENT(your number), Twilio AUTH_TOKEN, and SECRET_TOKEN (for GitHub) secrets to the respective values.

Finally, modify your githubWebhookHandler to send a text at the end using the sendText function you just made.

async function githubWebhookHandler(request) {
if (request.method !== "POST") {
return simpleResponse(
200,
"Please send a POST request :)"
)
}
try {
const formData = await request.json()
const headers = await request.headers
const action = headers.get("X-GitHub-Event")
const repo_name = formData.repository.full_name
const sender_name = formData.sender.login
if (!checkSignature(formData, headers)) {
return simpleResponse(403, "Wrong password, try again :P")
}
return await sendText(`${sender_name} casted spell: ${action} onto your repo ${repo_name}`)
} catch (e) {
return simpleResponse(
200,
`Error: ${e}`
)
}
}

Now, run the wrangler punlish command to deploy your Workers script:

$ wrangler publish

Video of receiving a text after pushing to a repo

Now, when you make an update (that you configured in the GitHub Webhook settings) to your repository, you will get a text soon after. If you have never used git before, refer to this quick guide to pushing to your repository.

You can reference the finished code on this GitHub repository.

By completing this tutorial, you have learned how to build webhooks using Workers, integrate Workers with GitHub and Twilio, and use Worker secrets with Wrangler.