Получаем оповещения от GitHub

7 min read

Данная статья является логическим продолжением истории о создании бота для Telegram, там мы разработали простого, но бесполезного пока, Telegram-бота и научили его разговаривать. Пришло время добавить ему более интересных функций.

Мы научимся получать уведомления от сервиса GitHub, взаимодействовать с GitHub API и Telegram API, напишем бота для передачи всех оповещений о новых коммитах GitHub репозитория в Telegram чат. Как показывает опыт работы нашей команды, это позволяет получать максимально оперативные сведения о работе над проектом в Telegram мессенджере и структурировать процесс разработки проектов. Начнем с этапа получения и обработки оповещений от GitHub.

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

Что такое API

API (Application Program Interface) - это интерфейс программирования приложений, специальный набор инструкций для взаимодействия сторонних разработчиков с вашим ресурсом. Сегодня многие крупные проекты имеют свои API, предоставляющие удобный механизм создания внешних приложений для сторонних разработчиков.

GitHub API

С GitHub API можно взаимодействовать посредством GET, POST запросов, даже через браузер. Для примера вы можете запросить информацию о пользователе. Подставьте вместо n0str свой GitHub-логин и пройдите по данному адресу в браузере:

https://api.github.com/users/n0str

GitHub ответит вам в формате JSON, который представляет из себя достаточно удобный способ представления информации в виде списков. JSON, ввиду своей универсальности, получил широкое распостранение, а его поддержка реализована в виде библиотек практически для каждого языка программирования. В ответе вы увидите свой логин, ссылки на аватарку, информацию профиля, количество репозиториев и прочие данные.

{ "login":"n0str", "id":988885, "avatar_url":"https://avatars.githubusercontent.com/u/988885?v=3", "gravatar_id":"", "url":"https://api.github.com/users/n0str", "html_url":"https://github.com/n0str", "type":"User", "site_admin":false, "name":"Menshikov Alexander", "public_repos":9, "public_gists":14, "followers":12, "following":20, "created_at":"2011-08-18T14:54:56Z", "updated_at":"2015-12-23T17:54:08Z" }

Мы не будем касаться вопросов работы с git; если вы не знаете как это делать, можете почитать заметки об этом:

Настраиваем прокси

Чтобы получать сообщения от GitHub, нужно сконфигурировать свой собственный сервер. Вы можете прочесть о настройке прокси в статье Простой веб-сервер с использованием Python и Flask.

В качестве прокси, будем использовать бесплатную программу ngrok. Ее главная задача - держать постоянное соединение и передавать вам всю полученную от сервера GitHub информацию. Запустите ее командой, передав в качестве параметра любой свободный порт:

./ngrok http 4567

Полученный ответ будет содержать несколько строк, среди которых вы найдете нечто подобное:

Forwarding http://ddabef45.ngrok.io -> 127.0.0.1:4567

Адрес http://ddabef45.ngrok.io нам понадобится позже.

Создаем локальный веб-сервер

Осталось поднять веб-сервер, который будет получать всю информацию по порту 4567. Воспользуемся кодом из предыдущей статьи о создании веб-сервера на Python Flask, слегка его модифицировав:

from flask import Flask, request, abort from json import loads app = Flask(__name__) @app.route("/", methods=['POST']) def index(): try: payload = loads(request.data) print payload["repository"]["name"] except: abort(400) return "Ok!" if __name__ == "__main__": app.run(host="0.0.0.0", port=4567)

Данный код проверяет, действительно ли вам передали POST запрос. Содержимое запроса можно сконвертировать в обычный массив с помощью библиотеки JSON и ее метода loads. В результате, в переменной payload окажется массив с информацией, а на экран будет выведено название репозитория.

GitHub Webhooks

Webhooks - это технология, работающая следующим образом: вы выбираете информация о каких событиях вам понадобятся, вводите адрес вашего веб-сервера и получаете от Github'а все сообщения в реальном времени. Для того, чтобы настроить Webhooks, перейдите в ваш репозиторий, выберите вкладку Settings и переключитесь на экран Webhooks & services.

После нажатия на кнопку Add webhook, потребуется ввести адрес своего сервера, который мы получили ранее (http://ddabef45.ngrok.io), в поле Payload URL и выбрать тип данных (JSON или urlencoded). В данной статье будем придерживаться формата JSON.

Проверка работы

Для проверки запустите сервер командой:

python server.py

Если все правильно сделано, осталось лишь выполнить команду git commit, затем команду git push и посмотреть результаты. В терминале, в котором вы запускали Flask сервер, отобразится имя репозитория (codex) и появится строка, отображающая POST запрос с HTTP кодом успеха (200).

Чтобы при экспериментировании с приложением вам не приходилось постоянно совершать одни и те же действия над репозиторием, можно воспользоваться встроенной в GitHub функцией повторной отправки сообщения по Payload URL. На странице Webhooks & Services кликните по соответствующему Webhook.

Откроется окно с информацией о вашем Webhook и его оповещениям. Кликнув по конкретному оповещению, вы откроете его содержание, среди которого можно видеть кнопку Redeliver. Клик по ней приводит к посылке повторного оповещения вашему веб-серверу.

Извлекаем полезные данные

Внесем немного изменений в код, чтобы вывести информацию о пользователе, который выполнил push запрос, количестве коммитов в запросе и название ветки репозитория, куда они были загружены. Код примет следующий вид:

from flask import Flask, request, abort from json import loads app = Flask(__name__) @app.route("/", methods=['POST']) def index(): try: payload = loads(request.data) # This code is new if request.headers.get('X-GitHub-Event') == "push": print "%s push %d commits to %s" \ % (payload["pusher"]["name"], len(payload["commits"]), payload["ref"]) # --> except: abort(400) return "Ok!" if __name__ == "__main__": # This code is new app.debug = True # --> app.run(host="0.0.0.0", port=4567)

А в терминале вы сможете увидеть строку приблизительно следующего содержания:

n0str push 1 commits to refs/heads/master

Также, вы могли заметить в коде строчку:

app.debug = True

Она позволяет вам получить дополнительную информацию об ошибках, в случае, если код написан неверно, или некоторые элементы массива оказались недоступны.

В следующей статье вы научите программу анализировать полученные от GitHub данные и посылать уведомления в ваш Telegram-чат.