INTEGRITY Документация

SMS-уведомления GitHub через Twilio

В этом руководстве вы научитесь создавать на Workers систему SMS-уведомлений об обновлениях репозитория GitHub. Ваш Worker будет отправлять вам текстовое сообщение через Twilio при появлении новой активности в репозитории.

Вы узнаете, как:

Анимированный gif с получением текстового сообщения на телефон после отправки изменений в репозиторий

Прежде чем начать

Во всех руководствах предполагается, что вы уже выполнили Руководство по началу работы, который поможет вам настроить аккаунт Cloudflare Workers, C3, а также Wrangler.

Создайте проект Worker

Для начала используйте npm create cloudflare@latest чтобы создать проект Worker в командной строке:

npm create cloudflare@latest -- github-twilio-notifications

Для настройки выберите следующие параметры:

Запишите URL, по которому было развёрнуто ваше приложение. Он понадобится вам при настройке вебхука GitHub.

cd github-twilio-notifications

Внутри вашего нового github-sms-notifications каталог, src/index.js представляет собой точку входа в ваше приложение Cloudflare Workers. Вы будете настраивать этот файл на протяжении большей части руководства.

Для этого руководства вам также понадобятся аккаунт GitHub и репозиторий. Если у вас их ещё нет, создать новую учётную запись GitHub и создать новый репозиторий чтобы продолжить это руководство.

Сначала создайте вебхук для своего репозитория, чтобы он отправлял обновления вашему Worker. Затем внутри Worker вы разберёте эти обновления. Наконец, вы отправите POST запрос к Twilio, чтобы отправить вам текстовое сообщение.

Готовый код можно посмотреть по этой репозиторий GitHub.


Настройте GitHub

Для начала настройте вебхук GitHub, который будет отправлять запрос в ваш Worker при обновлении репозитория:

  1. В репозитории GitHub перейдите на страницу Настройки > Webhooks > Добавить webhook.

  2. Укажите в качестве Payload URL значение /webhook путь по URL Worker, который вы записали при первом развёртывании приложения.

  3. В Тип контента раскрывающемся списке выберите application/json.

  4. В Секрет поле, введите секретный ключ по вашему выбору.

  5. В Какие события должны запускать этот webhook?, выберите Выбрать события по отдельности. Выберите события, о которых хотите получать уведомления (например, Pull requests, Отправки, а также Создание ветки или тега).

  6. Выберите Добавить webhook чтобы завершить настройку.

Инструкции по настройке вебхука в панели настроек вебхуков GitHub

Разбор ответа

Настроив локальное окружение, обработайте обновление репозитория с помощью Worker.

Изначально ваш сгенерированный index.js должен выглядеть следующим образом:

export default {
	async fetch(request, env, ctx) {
		return new Response("Hello World!");
	},
};

Используйте request.method свойство Request чтобы проверить, является ли запрос, поступающий в ваше приложение, POST запрос, и отправьте ответ об ошибке, если запрос не является POST запрос.

export default {
	async fetch(request, env, ctx) {
		if (request.method !== "POST") {
			return new Response("Please send a POST request!");
		}
	},
};

Затем проверьте, что запрос отправлен с правильным секретным ключом. GitHub добавляет хеш-подпись для каждую полезную нагрузку с помощью секретного ключа. Используйте вспомогательную функцию с именем checkSignature к запросу, чтобы убедиться в корректности хеша. После этого вы можете получить данные из вебхука, разобрав запрос как JSON.

async fetch(request, env, ctx) {
  if(request.method !== 'POST') {
    return new Response('Please send a POST request!');
  }
  try {
    const rawBody = await request.text();

    if (!checkSignature(rawBody, request.headers, env.GITHUB_SECRET_TOKEN)) {
      return new Response("Wrong password, try again", {status: 403});
    }
  } catch (e) {
    return new Response(`Error:  ${e}`);
  }
},

checkSignature функция будет использовать библиотеку crypto из Node.js, чтобы хешировать полученное тело запроса (payload) с помощью известного вам секретного ключа и убедиться, что оно совпадает с хешем запроса. GitHub использует HMAC hexdigest для вычисления хеша в формате SHA-256. Разместите эту функцию в начале index.js файл, перед вашим export.

import { createHmac, timingSafeEqual } from "node:crypto";
import { Buffer } from "node:buffer";

function checkSignature(text, headers, githubSecretToken) {
	const hmac = createHmac("sha256", githubSecretToken);
	hmac.update(text);
	const expectedSignature = hmac.digest("hex");
	const actualSignature = headers.get("x-hub-signature-256");

	const trusted = Buffer.from(`sha256=${expectedSignature}`, "ascii");
	const untrusted = Buffer.from(actualSignature, "ascii");

	return (
		trusted.byteLength == untrusted.byteLength &&
		timingSafeEqual(trusted, untrusted)
	);
}

Чтобы это заработало, нужно использовать wrangler secret put чтобы задать ваш GITHUB_SECRET_TOKEN. Этот токен является секретом, который вы указали ранее при настройке вебхука GitHub:

npx wrangler secret put GITHUB_SECRET_TOKEN

Добавьте флаг nodejs_compat в файл Wrangler:

{
	"compatibility_flags": [
		"nodejs_compat"
	]
}
compatibility_flags = [ "nodejs_compat" ]

Отправка текстового сообщения с помощью Twilio

Вы будете отправлять себе текстовые сообщения об активности в репозитории с помощью Twilio. Вам понадобятся аккаунт Twilio и номер телефона, способный принимать текстовые сообщения. Инструкции по настройке см. в руководстве Twilio. (Если вы впервые работаете с Twilio, у них есть интерактивная игра где можно узнать, как пользоваться их платформой, и получить бесплатные кредиты для новых пользователей сервиса.)

Затем можно создать вспомогательную функцию для отправки текстовых сообщений, отправив POST запрос к конечной точке Twilio API. См. справочник Twilio чтобы узнать больше об этом эндпоинте.

Создайте новую функцию с именем sendText() который будет отправлять запрос в Twilio:

async function sendText(accountSid, authToken, message) {
	const endpoint = `https://api.twilio.com/2010-04-01/Accounts/${accountSid}/Messages.json`;

	const encoded = new URLSearchParams({
		To: "%YOUR_PHONE_NUMBER%",
		From: "%YOUR_TWILIO_NUMBER%",
		Body: message,
	});

	const token = btoa(`${accountSid}:${authToken}`);

	const request = {
		body: encoded,
		method: "POST",
		headers: {
			Authorization: `Basic ${token}`,
			"Content-Type": "application/x-www-form-urlencoded",
		},
	};

	const response = await fetch(endpoint, request);
	const result = await response.json();

	return Response.json(result);
}

Чтобы это заработало, нужно задать несколько секретов, скрывающих ваш ACCOUNT_SID и AUTH_TOKEN из исходного кода. Секреты можно задать с помощью wrangler secret put в командной строке.

npx wrangler secret put TWILIO_ACCOUNT_SID
npx wrangler secret put TWILIO_AUTH_TOKEN

Измените ваш githubWebhookHandler чтобы отправить текстовое сообщение с помощью sendText функцию, которую вы только что создали.

async fetch(request, env, ctx) {
  if(request.method !== 'POST') {
    return new Response('Please send a POST request!');
  }
  try {
    const rawBody = await request.text();
    if (!checkSignature(rawBody, request.headers, env.GITHUB_SECRET_TOKEN)) {
      return new Response('Wrong password, try again', {status: 403});
    }

    const action = request.headers.get('X-GitHub-Event');
    const json = JSON.parse(rawBody);
    const repoName = json.repository.full_name;
    const senderName = json.sender.login;

    return await sendText(
      env.TWILIO_ACCOUNT_SID,
      env.TWILIO_AUTH_TOKEN,
      `${senderName} completed ${action} onto your repo ${repoName}`
    );
  } catch (e) {
    return new Response(`Error:  ${e}`);
  }
};

Выполните npx wrangler deploy команду, чтобы повторно развернуть проект Worker:

npx wrangler deploy
Видео о получении текстового сообщения после push в репозиторий

Теперь, когда вы вносите обновление (настроенное в GitHub Вебхук настройки) в ваш репозиторий, вскоре после этого вы получите текстовое сообщение. Если вы никогда раньше не использовали Git, обратитесь к Учебник по Git push и pull для отправки в ваш репозиторий.

См. готовый код на GitHub.

Пройдя это руководство, вы узнали, как создавать вебхуки с помощью Workers, интегрировать Workers с GitHub и Twilio, а также использовать секреты Worker в Wrangler.