Введение
При работе над проектом с несколькими разработчиками может быть неприятно, когда один человек отправляет изменения в репозиторий, а другой тут же начинает вносить изменения в старую версию кода. Подобные ошибки оправдывают создание скрипта для синхронизации репозиториев. Этот метод также можно применить в рабочей среде для быстрого внесения исправлений и других изменений.
Хотя существуют и другие решения для выполнения этой конкретной задачи, написание собственного сценария — это гибкий вариант, который оставляет место для будущих настроек.
GitHub позволяет настраивать веб-хуки для ваших репозиториев — события, которые отправляют HTTP-запросы при возникновении событий. Например, вы можете использовать веб-хук для уведомления о создании запроса на извлечение или публикации нового кода.
В этом руководстве вы создадите сервер Node.js, который будет прослушивать уведомления вебхука GitHub каждый раз, когда вы или кто-то другой отправляете код на GitHub. Этот скрипт автоматически обновляет репозиторий на удалённом сервере до последней версии кода, устраняя необходимость входа на сервер для внесения новых коммитов.
Предпосылки
- Настроенный сервер Ubuntu, включающий пользователя без прав root с привилегиями sudo и брандмауэр.
- Git установлен на вашем локальном компьютере.
- Node.js и npm устанавливаются на удаленном сервере с помощью официального PPA.
- Репозиторий на Github, содержащий код вашего проекта.
Шаг 1 — Настройка Webhook
Начнём с настройки хука для вашего репозитория. Этот шаг важен, поскольку без него Github не будет знать, какие события отправлять при возникновении каких-либо событий и куда их отправлять. Сначала мы создадим вебхук, а затем — сервер, который будет отвечать на его запросы.
Войдите в свою учётную запись GitHub и перейдите к репозиторию, который вы хотите отслеживать. Перейдите на вкладку «Настройки» в строке меню в верхней части страницы репозитория, затем нажмите «Веб-перехватчики» в левом навигационном меню. Нажмите «Добавить веб-перехватчик» в правом углу и введите пароль своей учётной записи при появлении запроса. Вы увидите страницу, которая выглядит примерно так:
- В поле «URL полезной нагрузки» введите http://your_server_ip:8080. Это адрес и порт сервера Node.js, который мы вскоре напишем.
- Измените тип контента на application/json. Скрипт, который мы пишем, ожидает данные в формате JSON и не может распознавать другие типы данных.
- В поле «Секрет» введите секретный пароль для этого вебхука. Этот секрет будет использоваться на сервере Node.js для аутентификации запросов и обеспечения их отправки с GitHub.
- Чтобы указать, какие события должны активировать этот вебхук, просто выберите событие push. Оно нам нужно только потому, что именно в этот момент код обновляется и должен быть синхронизирован с нашим сервером.
- Установите флажок Активно.
- Проверьте поля и нажмите «Добавить вебхук», чтобы создать его.
Сначала пинг не пройдёт, но будьте уверены, ваш вебхук теперь настроен. Теперь давайте клонируем репозиторий на сервер.
Шаг 2 — Клонирование репозитория на сервер
Наш скрипт может обновлять репозиторий, но не может его инициализировать, поэтому мы сделаем это сейчас. Войдите на свой сервер:
ssh sammy@your_server_ipУбедитесь, что вы находитесь в домашнем каталоге. Затем клонируйте репозиторий с помощью Git. Не забудьте заменить имя пользователя GitHub на sammy, а название проекта GitHub — на hello_hapi.
cd
git clone https://github.com/sammy/hello_hapi.gitБудет создан новый каталог с вашим проектом. Этот каталог понадобится вам на следующем шаге.
После клонирования проекта вы можете создать скрипт веб-перехвата.
Шаг 3 — Создание скрипта Webhook
Давайте создадим собственный сервер для прослушивания веб-хуков с GitHub. Мы напишем скрипт Node.js, который запустит веб-сервер на порту 8080. Сервер прослушивает веб-хуки, проверяет указанный нами секрет и скачивает последнюю версию кода с GitHub.
Перейдите в главное меню:
cd ~Создайте новый каталог для вашего скрипта веб-перехватчика под названием NodeWebhooks:
mkdir ~/NodeWebhooksЗатем перейдите в новый каталог:
cd ~/NodeWebhooksСоздайте новый файл с именем webhook.js в каталоге NodeWebhooks.
nano webhook.jsДобавьте в скрипт эти две строки:
/* Your codevar secret = "your_secret_here";
var repo = "/home/sammy/hello_hapi";... */Первая строка определяет переменную для хранения секрета, созданного на шаге 1, который подтверждает, что запросы поступают с GitHub. Вторая строка определяет переменную, содержащую полный путь к репозиторию, который вы хотите обновить на локальном диске. Он должен указывать на репозиторий, который вы извлекли на шаге 2.
Затем добавьте в скрипт следующие строки, импортирующие библиотеки http и crypto. Мы используем их для создания веб-сервера и секретного хеша, чтобы сравнить его с полученным на GitHub:
let http = require('http');
let crypto = require('crypto');Затем добавьте библиотеку child_process, чтобы вы могли запускать команды оболочки из своего скрипта:
const exec = require('child_process').exec;Затем добавьте этот код, чтобы определить новый веб-сервер, который будет обрабатывать запросы GitHub webhook, и, если запрос действителен, отправьте новую версию кода:
http.createServer(function (req, res) {
req.on('data', function(chunk) {
let sig = "sha1=" + crypto.createHmac('sha1', secret).update(chunk.toString()).digest('hex');
if (req.headers['x-hub-signature'] == sig) {
exec('cd ' + repo + ' && git pull');
}
});
res.end();
}).listen(8080);Функция http.createServer() запускает веб-сервер на порту 8080, который прослушивает входящие запросы от Github. В целях безопасности мы проверяем, что секретный ключ, указанный в запросе, совпадает с тем, который мы указали при создании вебхука на шаге 1. Этот секретный ключ отправляется в заголовке x-hub-signature как хешированная строка SHA1, поэтому мы хешируем наш секретный ключ и сравниваем его с тем, что отправляет нам GitHub.
Если запрос действителен, мы запускаем команду оболочки для обновления нашего локального репозитория с помощью git pull.
Готовый сценарий выглядит так:
const secret = "your_secret_here";
const repo = "~/your_repo_path_here/";
const http = require('http');
const crypto = require('crypto');
const exec = require('child_process').exec;
http.createServer(function (req, res) {
req.on('data', function(chunk) {
let sig = "sha1=" + crypto.createHmac('sha1', secret).update(chunk.toString()).digest('hex');
if (req.headers['x-hub-signature'] == sig) {
exec('cd ' + repo + ' && git pull');
}
});
res.end();
}).listen(8080);Если вы следовали руководству по начальной настройке сервера, вам необходимо разрешить этому веб-серверу взаимодействовать с внешней сетью, разрешив трафик через порт 8080:
sudo ufw allow 8080/tcpТеперь, когда наш скрипт готов, давайте убедимся, что он работает правильно.
Шаг 4 — Тестирование веб-перехватчиков
Мы можем протестировать наш вебхук, запустив его в командной строке с помощью Node. Запустите скрипт и оставьте процесс открытым в терминале:
cd ~/NodeWebhooks
nodejs webhook.jsВернитесь на страницу своего проекта на Github.com. Перейдите на вкладку «Настройки» в строке меню в верхней части страницы репозитория, а затем нажмите «Веб-хуки» в левом навигационном меню. Нажмите «Изменить» рядом с веб-хуком, который вы настроили на шаге 1. Прокрутите страницу вниз, чтобы увидеть раздел «Недавние коммиты», как показано на рисунке ниже:
Нажмите три точки справа, чтобы открыть кнопку «Повторить». Во время работы сервера узла нажмите кнопку «Повторить», чтобы повторно отправить запрос. После подтверждения отправки запроса вы увидите сообщение об успешном выполнении. На это указывает код ответа 200 OK после повторной отправки пинга.
Теперь мы можем гарантировать, что наш скрипт будет работать в фоновом режиме и запускаться при загрузке системы. Сочетание клавиш CTRL+C остановит сервер веб-перехвата узла.
Шаг 5 — Установка Webhook как службы Systemd
systemd — это менеджер задач Ubuntu для управления службами. Мы запустим службу, которая позволит нам запускать скрипт веб-перехвата при загрузке системы и управлять ею, как любой другой службой, с помощью команд systemd.
Начните с создания нового файла службы:
sudo nano /etc/systemd/system/webhook.service
Добавьте следующую конфигурацию в файл сервиса, которая указывает systemd, как запускать скрипт. Она указывает Systemd, где найти наш скрипт узла, и описывает наш сервис.
Обязательно замените Sami своим именем пользователя.
[Unit]
Description=Github webhook
After=network.target
[Service]
Environment=NODE_PORT=8080
Type=simple
User=sammy
ExecStart=/usr/bin/nodejs /home/sammy/NodeWebhooks/webhook.js
Restart=on-failure
[Install]
WantedBy=multi-user.targetВключите запуск новой службы при загрузке системы:
sudo systemctl enable webhook.serviceТеперь запустите службу:
sudo systemctl start webhookУбедитесь, что служба запущена:
sudo systemctl status webhookВы увидите следующий вывод, указывающий на то, что служба активна:
Output
● webhook.service - Github webhook
Loaded: loaded (/etc/systemd/system/webhook.service; enabled; vendor preset: enabled)
Active: active (running) since Fri 2018-08-17 19:28:41 UTC; 6s ago
Main PID: 9912 (nodejs)
Tasks: 6
Memory: 7.6M
CPU: 95ms
CGroup: /system.slice/webhook.service
└─9912 /usr/bin/nodejs /home/sammy/NodeWebhooks/webhook.jsТеперь вы можете отправлять новые коммиты в свой репозиторий и видеть изменения на своем сервере.
На настольном устройстве эмулируйте репозиторий:
git clone https://github.com/sammy/hello_hapi.gitИзмените один из файлов в репозитории. Затем закоммитьте файл и отправьте свой код на GitHub.
git add index.js
git commit -m "Update index file"
git push origin masterВеб-хук будет активирован, и ваши изменения появятся на вашем сервере.
Результат
Вы настроили скрипт Node.js, который автоматически развёртывает новые коммиты в удалённом репозитории. Вы можете использовать этот процесс для настройки дополнительных репозиториев, которые хотите отслеживать. Вы даже можете настроить его для развёртывания веб-сайта или приложения в рабочей среде при отправке репозитория.











