Wiki
Webhooks
Notificaciones salientes por repositorio (Discord, Slack, Teams, custom) en check-ins y resúmenes de actividad. Creación, formato de los mensajes, variables de plantilla, protección SSRF.
Introducción
Un webhook envía una notificación saliente a un servicio externo (Discord, Slack, Microsoft Teams, o una URL de tu elección) cada vez que ocurre un evento en un repositorio (un proyecto versionado en el servidor): un check-in, o un resumen de actividad periódico. Es la forma más sencilla de mantener a un equipo al tanto sin que abra el cliente: un mensaje cae en tu canal cuando alguien envía trabajo.
Los webhooks se configuran por repositorio, en el panel de administración del cliente de escritorio, en la pestaña Webhooks. Un repositorio puede tener varios webhooks (por ejemplo uno a Discord para todo el equipo, uno a un Slack privado para los leads).
Acceso y roles
La gestión de los webhooks está reservada a los administradores del repositorio: un super admin
(rol admin) en cualquier repositorio, o un project_admin en los repositorios
que administra. Los demás roles no ven esta pestaña.
Crear un webhook
1. Abrir la pestaña Webhooks
En el panel de administración, elige primero el repositorio en el selector de la fila PROJECT, luego abre la pestaña Webhooks de esa misma fila: un webhook pertenece a un repositorio. Un repositorio que no tiene ninguno muestra No webhooks configured.
2. Abrir el formulario
Haz clic en Add Webhook, arriba a la derecha de la pestaña. La ventana Create Webhook se abre, vacía.
3. Rellenar los campos
Dos campos son obligatorios, Name y URL, y al menos un evento debe estar seleccionado en Events (son píldoras clicables, no una lista desplegable). El Type debe corresponder al servicio al que apunta la URL.
| Campo | Valor |
|---|---|
| Name | Una etiqueta para reconocerlo (p. ej. Discord équipe). Obligatorio. |
| URL | La URL del webhook proporcionada por el servicio de destino. Obligatoria. Consulta Seguridad para las URL rechazadas. |
| Type | discord, slack, teams o custom. |
| Events | Al menos uno es obligatorio. En la práctica: checkin y activity_summary. Consulta Eventos acerca de checkout. |
| Enabled | Interruptor de activación (visible al editar y desde la lista). |
Para obtener la URL en el lado de Discord: Configuración del canal → Integraciones → Webhooks → Nuevo webhook → Copiar URL, se detalla en el tutorial de más abajo. En el lado de Slack: crea un Incoming Webhook en los ajustes de la aplicación de Slack. En el lado de Teams: Conectores → Incoming Webhook en el canal.
4. Validar y luego enviar una prueba
Haz clic en Create Webhook. El webhook aparece en la lista, activo. En su fila, haz clic en el icono de avión Send test: uVersion envía una notificación de prueba al servicio y muestra el resultado al final de la fila, una marca verde o una cruz con el código HTTP devuelto. Hazlo ahora: es la única forma de saber que la URL y el tipo son correctos antes de depender de este webhook.
Tutorial: webhook de Discord
Es el caso más común. La parte de «obtener la URL» ocurre íntegramente dentro de Discord, una sola vez.
En el lado de Discord: obtener la URL
- Abre Discord y ve a tu servidor. Elige (o crea) el canal de texto que recibirá las notificaciones, por ejemplo
#uversion. - Pasa el ratón sobre el nombre del canal y haz clic en el icono de engranaje («Editar canal»).
- En el menú de la izquierda, abre la pestaña Integraciones.
- Haz clic en Webhooks y luego en Nuevo webhook. Discord crea uno automáticamente, vinculado a este canal.
- Haz clic en el webhook creado para abrirlo. Ponle un nombre (por ejemplo
uVersion) y comprueba que el canal de destino es el correcto. La imagen de avatar es opcional. - Haz clic en Copiar URL del webhook. La URL se parece a
https://discord.com/api/webhooks/123456789/AbCdEf....
En el lado de uVersion: conectar la URL
Sigue el procedimiento Crear un webhook de más arriba con estos valores:
Name una etiqueta para ti (p. ej. Discord équipe), URL la que
acabas de copiar, Type discord (imprescindible para que el mensaje salga como embed
de Discord), Events checkin. Termina con Send test: un mensaje
debería aparecer en el canal de Discord en unos segundos.
Si la prueba falla con un código HTTP 401 o 404, la URL es incorrecta o el webhook se
eliminó en el lado de Discord: vuelve a copiar la URL. Si no llega nada aunque la prueba esté en verde, comprueba que estás mirando
el canal correcto y que el webhook no ha sido desactivado en Discord.
Tipos y formatos
El Type determina cómo uVersion formatea el mensaje antes de enviarlo. Elige el que corresponda al servicio al que apunta la URL, de lo contrario el mensaje llegará mal formateado (o será rechazado por el servicio).
| Type | Formato enviado |
|---|---|
discord | Embed de Discord (título, color, campos). |
slack | Payload de Slack (bloques de mensaje). |
teams | Tarjeta de Microsoft Teams (MessageCard). |
custom | Cuerpo JSON definido íntegramente por ti: consulta Webhooks personalizados. |
Eventos
Dos eventos son realmente emitidos por el servidor:
| Evento | Se dispara cuando… |
|---|---|
checkin | Un usuario envía un commit al repositorio. |
activity_summary | El planificador del servidor produce un resumen de actividad periódico (diario / semanal). |
checkout: casilla presente, evento nunca emitido
El formulario ofrece una tercera casilla, checkout, destinada a señalar el bloqueo de un archivo
(un bloqueo es la reserva que un usuario pone sobre un archivo mientras lo modifica).
Está declarada pero nunca emitida hasta la fecha: marcarla no provocará ninguna notificación.
No cuentes con ella, y no la uses como única selección: un webhook que solo tenga este evento marcado
permanecerá en silencio para siempre.
Marca únicamente lo que tu canal necesita. En la práctica, la combinación útil es checkin para el
hilo de trabajo del equipo, y activity_summary para un repaso periódico.
Webhooks personalizados
Con el tipo custom aparecen dos campos adicionales: Custom Headers (JSON)
y Custom Template (JSON). Permiten integrar cualquier servicio que acepte un POST JSON.
Template
La plantilla es el cuerpo JSON enviado. uVersion reemplaza en ella las variables entre dobles llaves por los valores del evento. Ejemplo:
{"text": "{{event_type}} par {{username}} dans {{repository}}"}
Variables disponibles:
| Variable | Contenido |
|---|---|
{{event_type}} | Tipo de evento (checkin o activity_summary). |
{{repository}} | Nombre del repositorio. |
{{username}} | Usuario que originó el evento. |
{{message}} | Mensaje de commit (para un check-in). |
{{file_count}} | Número de archivos afectados. |
{{commit_hash}} | Hash del commit. |
{{timestamp}} | Marca de tiempo del evento. |
Headers
Un objeto JSON de encabezados HTTP para adjuntar a la solicitud, por ejemplo un token de autenticación:
{"Authorization": "Bearer VOTRE_JETON"}
Por defecto {} (ningún encabezado). Los encabezados reservados al transporte
(host, content-length, transfer-encoding, connection)
se eliminan automáticamente y no pueden sobrescribirse.
Probar, activar, eliminar
Cada webhook de la lista ofrece las siguientes acciones:
- Send test (icono de avión): envía una notificación de prueba al servicio y muestra un resultado en línea (marca verde o cruz). Útil para verificar la URL y el tipo antes de depender de él.
- Interruptor: activa / desactiva el webhook sin eliminarlo.
- Edit: modificar cualquier campo.
- Delete: eliminación definitiva (se pide confirmación).
Seguridad: protección SSRF
Un webhook hace que sea el servidor quien emita una solicitud HTTP. Para evitar que una URL maliciosa sirva para sondear la red interna del servidor (ataque SSRF), uVersion aplica una protección estricta en la creación, en la modificación y en la prueba:
- El esquema debe ser
httpohttps. Cualquier otro esquema se rechaza. - El nombre de host se resuelve por DNS, y se verifica cada dirección IP obtenida. El webhook
se rechaza si alguna apunta a una dirección no pública: loopback, redes privadas (RFC1918), link-local,
broadcast, rango CGNAT
100.64.0.0/10, metadatos de nube169.254.169.254, ULA / link-local IPv6, y sus equivalentes IPv4-mapped-IPv6. - No se siguen las redirecciones HTTP (por lo que un 307 a un host interno no puede eludir la protección).
- El cuerpo de la respuesta de origen nunca se devuelve al cliente (sin oráculo SSRF).
En la práctica: una URL de webhook debe apuntar a un servicio público (Discord, Slack, Teams, o
tu propio endpoint accesible desde Internet). Una URL a localhost, una IP privada
(10.x, 192.168.x, 172.16-31.x) o un servicio interno se rechaza con un
mensaje «Webhook URL refused: …».
Errores frecuentes
El tipo no corresponde al servicio
Enviar un formato de Discord a una URL de Slack (o al revés) produce un mensaje mal formateado o un rechazo en el lado del servicio. El campo Type debe corresponder a la URL. En caso de duda, haz un Send test.
Ningún evento marcado
Un webhook sin evento nunca se dispara. El cliente bloquea el guardado mientras no haya ningún evento seleccionado («At least one event is required»).
URL interna rechazada
Si pruebas contra un servicio en tu propia máquina o tu LAN, la protección SSRF lo rechaza. Expón el servicio en una URL pública (o un túnel) para usarlo como destino de webhook.
Webhook desactivado olvidado
Un webhook desactivado permanece en la lista pero no envía nada. Si las notificaciones se han quedado en silencio, comprueba primero el interruptor de activación antes de sospechar de la URL.