Wiki
Webhooks
Notificações de saída por repositório (Discord, Slack, Teams, custom) em check-ins e resumos de atividade. Criação, formato das mensagens, variáveis de template, proteção SSRF.
Introdução
Um webhook envia uma notificação de saída para um serviço externo (Discord, Slack, Microsoft Teams, ou uma URL de sua escolha) toda vez que um evento acontece em um repositório (um projeto versionado no servidor): um check-in, ou um resumo de atividade periódico. É a forma mais simples de manter uma equipe informada sem que ela abra o cliente: uma mensagem cai no seu canal quando alguém envia trabalho.
Os webhooks são configurados por repositório, no painel de administração do cliente desktop, na aba Webhooks. Um repositório pode ter vários webhooks (por exemplo um para o Discord para toda a equipe, um para um Slack privado para os leads).
Acesso e papéis
O gerenciamento dos webhooks é reservado aos administradores do repositório: um super admin
(papel admin) em qualquer repositório, ou um project_admin nos repositórios
que ele administra. Os demais papéis não veem essa aba.
Criar um webhook
1. Abrir a aba Webhooks
No painel de administração, escolha primeiro o repositório no seletor da linha PROJECT, depois abra a aba Webhooks dessa mesma linha: um webhook pertence a um repositório. Um repositório que não tem nenhum exibe No webhooks configured.
2. Abrir o formulário
Clique em Add Webhook, no canto superior direito da aba. A janela Create Webhook abre, vazia.
3. Preencher os campos
Dois campos são obrigatórios, Name e URL, e ao menos um evento deve estar selecionado em Events (são pílulas clicáveis, não uma lista suspensa). O Type deve corresponder ao serviço para o qual a URL aponta.
| Campo | Valor |
|---|---|
| Name | Um rótulo para reconhecê-lo (ex. Discord équipe). Obrigatório. |
| URL | A URL do webhook fornecida pelo serviço de destino. Obrigatória. Veja Segurança para as URLs recusadas. |
| Type | discord, slack, teams ou custom. |
| Events | Ao menos um é obrigatório. Na prática: checkin e activity_summary. Veja Eventos sobre checkout. |
| Enabled | Interruptor de ativação (visível na edição e a partir da lista). |
Para obter a URL no lado do Discord: Configurações do canal → Integrações → Webhooks → Novo Webhook → Copiar URL, detalhado no tutorial abaixo. No lado do Slack: crie um Incoming Webhook nas configurações do aplicativo do Slack. No lado do Teams: Conectores → Incoming Webhook no canal.
4. Validar e depois enviar um teste
Clique em Create Webhook. O webhook aparece na lista, ativo. Na linha dele, clique no ícone de avião Send test: o uVersion envia uma notificação de teste ao serviço e exibe o resultado no fim da linha, uma marca verde ou uma cruz com o código HTTP retornado. Faça isso agora: é a única forma de saber que a URL e o tipo estão corretos antes de contar com este webhook.
Tutorial: webhook do Discord
É o caso mais comum. A parte de «obter a URL» acontece inteiramente dentro do Discord, uma única vez.
No lado do Discord: obter a URL
- Abra o Discord e vá ao seu servidor. Escolha (ou crie) o canal de texto que receberá as notificações, por exemplo
#uversion. - Passe o mouse sobre o nome do canal e clique no ícone de engrenagem («Editar Canal»).
- No menu à esquerda, abra a aba Integrações.
- Clique em Webhooks e depois em Novo Webhook. O Discord cria um automaticamente, vinculado a este canal.
- Clique no webhook criado para abri-lo. Dê a ele um nome (por exemplo
uVersion) e verifique se o canal de destino é o correto. Uma imagem de avatar é opcional. - Clique em Copiar URL do Webhook. A URL se parece com
https://discord.com/api/webhooks/123456789/AbCdEf....
No lado do uVersion: conectar a URL
Percorra o procedimento Criar um webhook acima com estes valores: Name um
rótulo para você (ex. Discord équipe), URL a que você acabou de copiar,
Type discord (indispensável para que a mensagem saia como embed do Discord),
Events checkin. Termine com Send test: uma mensagem deve aparecer
no canal do Discord em alguns segundos.
Se o teste falhar com um código HTTP 401 ou 404, a URL está errada ou o webhook foi
excluído no lado do Discord: copie a URL novamente. Se nada chegar mesmo com o teste verde, verifique se você está olhando
o canal correto e se o webhook não foi desativado no Discord.
Tipos e formatos
O Type determina como o uVersion formata a mensagem antes de enviá-la. Escolha aquele que corresponde ao serviço apontado pela URL, senão a mensagem chegará mal formatada (ou será rejeitada pelo serviço).
| Type | Formato enviado |
|---|---|
discord | Embed do Discord (título, cor, campos). |
slack | Payload do Slack (blocos de mensagem). |
teams | Cartão do Microsoft Teams (MessageCard). |
custom | Corpo JSON inteiramente definido por você: veja Webhooks personalizados. |
Eventos
Dois eventos são realmente emitidos pelo servidor:
| Evento | Dispara quando… |
|---|---|
checkin | Um usuário envia um commit ao repositório. |
activity_summary | Um resumo de atividade periódico é produzido pelo agendador do servidor (diário / semanal). |
checkout: caixa presente, evento nunca emitido
O formulário oferece uma terceira caixa, checkout, destinada a sinalizar o bloqueio de um arquivo
(um bloqueio é a reserva que um usuário coloca em um arquivo enquanto o modifica).
Ela está declarada mas nunca emitida até hoje: marcá-la não provocará nenhuma notificação.
Não conte com ela, e não a use como única seleção: um webhook que tenha apenas este evento marcado
permanecerá em silêncio para sempre.
Marque apenas o que o seu canal precisa. Na prática, a combinação útil é checkin para o fluxo de
trabalho da equipe, e activity_summary para um resumo periódico.
Webhooks personalizados
Com o tipo custom, aparecem dois campos adicionais: Custom Headers (JSON)
e Custom Template (JSON). Eles permitem integrar qualquer serviço que aceite um POST JSON.
Template
O template é o corpo JSON enviado. O uVersion substitui nele as variáveis entre chaves duplas pelos valores do evento. Exemplo:
{"text": "{{event_type}} par {{username}} dans {{repository}}"}
Variáveis disponíveis:
| Variável | Conteúdo |
|---|---|
{{event_type}} | Tipo de evento (checkin ou activity_summary). |
{{repository}} | Nome do repositório. |
{{username}} | Usuário que originou o evento. |
{{message}} | Mensagem de commit (para um check-in). |
{{file_count}} | Número de arquivos afetados. |
{{commit_hash}} | Hash do commit. |
{{timestamp}} | Carimbo de data/hora do evento. |
Headers
Um objeto JSON de cabeçalhos HTTP para anexar à requisição, por exemplo um token de autenticação:
{"Authorization": "Bearer VOTRE_JETON"}
Por padrão {} (nenhum cabeçalho). Os cabeçalhos reservados ao transporte
(host, content-length, transfer-encoding, connection)
são removidos automaticamente e não podem ser sobrescritos.
Testar, ativar, excluir
Cada webhook da lista oferece as seguintes ações:
- Send test (ícone de avião): envia uma notificação de teste ao serviço e exibe um resultado em linha (marca verde ou cruz). Útil para verificar a URL e o tipo antes de contar com ele.
- Interruptor: ativa / desativa o webhook sem excluí-lo.
- Edit: modificar qualquer campo.
- Delete: exclusão definitiva (confirmação solicitada).
Segurança: proteção SSRF
Um webhook faz com que uma requisição HTTP seja emitida pelo servidor. Para evitar que uma URL maliciosa sirva para sondar a rede interna do servidor (ataque SSRF), o uVersion aplica uma proteção estrita na criação, na modificação e no teste:
- O esquema deve ser
httpouhttps. Qualquer outro esquema é recusado. - O nome de host é resolvido por DNS, e cada endereço IP obtido é verificado. O webhook
é recusado se algum apontar para um endereço não público: loopback, redes privadas (RFC1918), link-local,
broadcast, faixa CGNAT
100.64.0.0/10, metadados de nuvem169.254.169.254, ULA / link-local IPv6, e seus equivalentes IPv4-mapped-IPv6. - Os redirecionamentos HTTP não são seguidos (então um 307 para um host interno não pode contornar a proteção).
- O corpo da resposta de origem nunca é retornado ao cliente (sem oráculo SSRF).
Na prática: uma URL de webhook deve apontar para um serviço público (Discord, Slack, Teams, ou
o seu próprio endpoint acessível a partir da Internet). Uma URL para localhost, um IP privado
(10.x, 192.168.x, 172.16-31.x) ou um serviço interno é recusada com uma
mensagem «Webhook URL refused: …».
Armadilhas comuns
O tipo não corresponde ao serviço
Enviar um formato do Discord para uma URL do Slack (ou o inverso) produz uma mensagem mal formatada ou uma rejeição no lado do serviço. O campo Type deve corresponder à URL. Na dúvida, faça um Send test.
Nenhum evento marcado
Um webhook sem evento nunca dispara. O cliente bloqueia o salvamento enquanto nenhum evento estiver selecionado («At least one event is required»).
URL interna recusada
Se você testar contra um serviço na sua própria máquina ou na sua LAN, a proteção SSRF o recusa. Exponha o serviço em uma URL pública (ou um túnel) para usá-lo como destino de webhook.
Webhook desativado esquecido
Um webhook desativado permanece na lista mas não envia nada. Se as notificações silenciaram, verifique primeiro o interruptor de ativação antes de suspeitar da URL.