Introducción
Al trabajar en un proyecto con varios desarrolladores, puede ser frustrante que una persona suba código a un repositorio y luego otra empiece a modificar una versión antigua. Errores como este justifican configurar un script para mantener los repositorios sincronizados. También puedes aplicar este método en un entorno de producción para realizar correcciones y otros cambios rápidamente.
Si bien existen otras soluciones para completar esta tarea específica, escribir su propio script es una opción flexible que deja espacio para una personalización futura.
GitHub te permite configurar webhooks para tus repositorios, que son eventos que envían solicitudes HTTP cuando se producen eventos. Por ejemplo, puedes usar un webhook para recibir notificaciones cuando alguien crea una solicitud de extracción o envía código nuevo.
En esta guía, crearás un servidor Node.js que recibe una notificación de webhook de GitHub cada vez que tú u otra persona sube código a GitHub. Este script actualiza automáticamente un repositorio en un servidor remoto con la última versión del código, eliminando la necesidad de iniciar sesión en el servidor para realizar nuevas confirmaciones.
Requisitos previos
- Un servidor Ubuntu configurado que incluye un usuario no root con privilegios de sudo y un firewall.
- Git está instalado en su máquina local.
- Node.js y npm se instalan en el servidor remoto utilizando el PPA oficial.
- Un repositorio en Github que contiene el código de su proyecto.
Paso 1: Configurar el webhook
Comenzaremos configurando un webhook para tu repositorio. Este paso es importante porque, sin él, Github no sabrá qué eventos enviar cuando algo sucede ni a dónde enviarlos. Primero, crearemos el webhook y, luego, un servidor que responderá a sus solicitudes.
Inicia sesión en tu cuenta de GitHub y navega hasta el repositorio que quieras monitorizar. Haz clic en la pestaña Configuración en la barra de menú de la parte superior de la página del repositorio y, a continuación, en Webhooks en el menú de navegación izquierdo. Haz clic en Añadir webhook en la esquina derecha e introduce la contraseña de tu cuenta cuando se te solicite. Verás una página similar a esta:
- En el campo URL de carga útil, ingrese http://your_server_ip:8080. Esta es la dirección y el puerto del servidor Node.js que escribiremos pronto.
- Cambie el tipo de contenido a application/json. El script que estamos escribiendo espera datos JSON y no puede comprender otros tipos de datos.
- En "Secreto", introduce una contraseña secreta para este webhook. Usarás esta contraseña en tu servidor Node.js para autenticar las solicitudes y garantizar que se envíen desde GitHub.
- Para especificar qué eventos quieres que activen este webhook, simplemente selecciona el evento push. Solo necesitamos el evento push porque es cuando se actualiza el código y debe sincronizarse con nuestro servidor.
- Seleccione la casilla de verificación Activo.
- Revise los campos y haga clic en Agregar webhook para crearlo.
El ping fallará inicialmente, pero ten por seguro que tu webhook ya está configurado. Ahora, clonemos el repositorio al servidor.
Paso 2 – Clonar el repositorio al servidor
Nuestro script puede actualizar un repositorio, pero no inicializarlo, así que lo haremos ahora. Inicie sesión en su servidor:
ssh sammy@your_server_ipAsegúrate de estar en tu directorio personal. Luego, usa Git para clonar tu repositorio. Asegúrate de reemplazar tu nombre de usuario de GitHub por sammy y el nombre de tu proyecto de GitHub por hello_hapi.
cd
git clone https://github.com/sammy/hello_hapi.gitEsto creará un nuevo directorio que contendrá tu proyecto. Lo usarás en el siguiente paso.
Con su proyecto clonado, puede crear el script del webhook.
Paso 3: Crear un script de webhook
Vamos a crear nuestro propio servidor para escuchar las solicitudes de webhook de GitHub. Escribiremos un script de Node.js que inicie un servidor web en el puerto 8080. El servidor escucha las solicitudes de webhook, verifica el secreto especificado y extrae la última versión del código de GitHub.
Vaya a su menú principal:
cd ~Cree un nuevo directorio para su script de webhook llamado NodeWebhooks:
mkdir ~/NodeWebhooksLuego vaya al nuevo directorio:
cd ~/NodeWebhooksCree un nuevo archivo llamado webhook.js en el directorio NodeWebhooks.
nano webhook.jsAñade estas dos líneas al script:
/* Your codevar secret = "your_secret_here";
var repo = "/home/sammy/hello_hapi";... */La primera línea define una variable que almacena el secreto creado en el paso 1 y que verifica que las solicitudes provienen de GitHub. La segunda línea define una variable que contiene la ruta completa al repositorio que desea actualizar en su disco local. Esta debe apuntar al repositorio que extrajo en el paso 2.
A continuación, agregue estas líneas que importan las bibliotecas http y crypto al script. Las usaremos para crear nuestro servidor web y el hash secreto para compararlo con lo que obtenemos de GitHub:
let http = require('http');
let crypto = require('crypto');A continuación, agregue la biblioteca child_process para poder ejecutar comandos de shell desde su script:
const exec = require('child_process').exec;A continuación, agregue este código para definir un nuevo servidor web que manejará las solicitudes de webhook de GitHub y, si una solicitud es válida, enviará la nueva versión del código:
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);La función http.createServer() inicia un servidor web en el puerto 8080 que recibe las solicitudes entrantes de GitHub. Por seguridad, verificamos que el secreto incluido en la solicitud coincida con el especificado al crear el webhook en el paso 1. Este secreto se envía en el encabezado x-hub-signature como una cadena con hash SHA1, por lo que lo comparamos con lo que GitHub nos envía.
Si la solicitud es válida, ejecutamos un comando de shell para actualizar nuestro repositorio local usando git pull.
El script completo se ve así:
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);Si siguió la guía de configuración inicial del servidor, debe permitir que este servidor web se comunique con la web externa permitiendo el tráfico en el puerto 8080:
sudo ufw allow 8080/tcpAhora que nuestro script está en su lugar, asegurémonos de que funcione correctamente.
Paso 4: Prueba del webhook
Podemos probar nuestro webhook usando node para ejecutarlo en la línea de comandos. Inicie el script y deje el proceso abierto en su terminal:
cd ~/NodeWebhooks
nodejs webhook.jsRegresa a la página de tu proyecto en Github.com. Haz clic en la pestaña Configuración en la barra de menú, en la parte superior de la página de tu repositorio, y luego en Webhooks en el menú de navegación izquierdo. Haz clic en Editar junto al webhook que configuraste en el paso 1. Desplázate hacia abajo para ver la sección "Commits recientes", como se muestra en la imagen a continuación.
Presione los tres puntos a la derecha para que aparezca el botón "Reenviar". Con el servidor de nodo en ejecución, haga clic en "Reenviar" para reenviar la solicitud. Tras confirmar que desea enviar la solicitud, verá una respuesta correcta. Esto se indica con un código de respuesta "200 OK" tras la reenvío del ping.
Ahora podemos asegurarnos de que nuestro script se ejecute en segundo plano y se inicie al arrancar. Usar Ctrl+C detendrá el servidor webhook del nodo.
Paso 5: Instalar Webhook como un servicio Systemd
systemd es el administrador de tareas de Ubuntu para controlar los servicios. Iniciaremos un servicio que nos permitirá iniciar nuestro script de webhook al arrancar y usar comandos de systemd para administrarlo como cualquier otro servicio.
Comience creando un nuevo archivo de servicio:
sudo nano /etc/systemd/system/webhook.service
Agregue la siguiente configuración al archivo de servicio que indica a systemd cómo ejecutar el script. Esto indica a Systemd dónde encontrar nuestro script de nodo y describe nuestro servicio.
Asegúrate de reemplazar Sami con tu nombre de usuario.
[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.targetHabilite el nuevo servicio para que se inicie al arrancar el sistema:
sudo systemctl enable webhook.serviceAhora inicia el servicio:
sudo systemctl start webhookAsegúrese de que el servicio se haya iniciado:
sudo systemctl status webhookVerá la siguiente salida indicando que el servicio está activo:
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.jsAhora puedes enviar nuevas confirmaciones a tu repositorio y ver los cambios en tu servidor.
Desde su dispositivo de escritorio, emule el repositorio:
git clone https://github.com/sammy/hello_hapi.gitModifica uno de los archivos del repositorio. Luego, confirma el archivo y sube tu código a GitHub.
git add index.js
git commit -m "Update index file"
git push origin masterEl webhook se activará y sus cambios aparecerán en su servidor.
Resultado
Has configurado un script de Node.js que implementa automáticamente nuevas confirmaciones en un repositorio remoto. Puedes usar este proceso para configurar repositorios adicionales que quieras supervisar. Incluso puedes configurarlo para implementar un sitio web o una aplicación en producción al enviar tu repositorio.











