Wiki
Webhook
按仓库配置的出站通知(Discord、Slack、Teams、custom),在签入、签出和活动摘要时触发。创建、消息格式、模板变量、SSRF 防护。
简介
每当仓库中发生某个事件时,Webhook 会向外部服务(Discord、Slack、Microsoft Teams, 或你选择的任意 URL)发送一条出站通知。事件是指签入、签出, 或周期性的活动摘要。这是在不打开客户端的情况下让团队保持知情的最简单方式: 当有人提交工作时,一条消息会出现在你的频道里。
Webhook 是按仓库配置的,位于桌面客户端管理面板的 Webhooks 标签页。一个仓库可以有多个 Webhook(例如面向整个团队发往 Discord 的一个, 面向负责人发往私有 Slack 的一个)。
访问权限与角色
Webhook 管理仅限仓库管理员:任意仓库上的超级管理员
(admin 角色),或所管理仓库上的 project_admin。
其他角色看不到此标签页。
创建 Webhook
- 打开管理面板,选择仓库,然后进入 Webhooks 标签页。
- 点击 Add Webhook。
- 填写各字段,然后点击 Create。
| 字段 | 值 |
|---|---|
| Name | 便于日后辨认的标签(例如 Discord équipe)。必填。 |
| URL | 目标服务提供的 Webhook URL。必填。被拒绝的 URL 见安全。 |
| Type | discord、slack、teams 或 custom。 |
| Events | checkin、checkout、activity_summary 中的一个或多个。至少必选一个。 |
| Enabled | 启用开关(编辑时以及在列表中可见)。 |
在 Discord 端获取 URL:频道设置 → 整合 → Webhook → 新建 Webhook → 复制 Webhook URL。在 Slack 端:在 Slack 应用设置中创建一个 Incoming Webhook。 在 Teams 端:在频道上连接器 → Incoming Webhook。
教程:Discord Webhook
这是最常见的情况。“获取 URL”这一步完全在 Discord 内完成,仅需一次。
Discord 端:获取 URL
- 打开 Discord 并进入你的服务器。选择(或创建)将接收通知的文字频道,例如
#uversion。 - 将鼠标悬停在频道名称上,点击齿轮图标(“编辑频道”)。
- 在左侧菜单中,打开 整合 标签。
- 点击 Webhook,然后点击 新建 Webhook。Discord 会自动创建一个并关联到该频道。
- 点击已创建的 Webhook 将其打开。为它取一个名称(例如
uVersion),并确认目标频道正确。头像图片为可选。 - 点击 复制 Webhook URL。URL 形如
https://discord.com/api/webhooks/123456789/AbCdEf...。
uVersion 端:接入 URL
- 在桌面客户端中打开管理面板,选择仓库,然后进入 Webhooks 标签页。
- 点击 Add Webhook。
- Name:给自己看的标签(例如
Discord équipe)。 - URL:粘贴从 Discord 复制的 URL。
- Type:选择
discord(这样消息才会被格式化为 Discord 嵌入内容,必不可少)。 - Events:勾选所需事件,例如
checkin。 - 点击 Create。
- 在该 Webhook 那一行点击 Send test:几秒内应有一条测试消息出现在 Discord 频道中。
如果测试以 HTTP 401 或 404 状态失败,说明 URL 有误或该 Webhook 已在
Discord 端被删除:请重新复制 URL。如果测试为绿色却什么都没收到,请检查你查看的是否为正确的频道,
以及该 Webhook 是否在 Discord 中被停用。
类型与格式
Type 决定 uVersion 在发送前如何格式化消息。请选择与 URL 所指服务相匹配的类型, 否则消息会以错误的格式到达(或被服务拒绝)。
| Type | 发送的格式 |
|---|---|
discord | Discord 嵌入内容(标题、颜色、字段)。 |
slack | Slack 载荷(消息块)。 |
teams | Microsoft Teams 卡片(MessageCard)。 |
custom | 完全由你定义的 JSON 主体:见自定义 Webhook。 |
事件
| 事件 | 触发时机… |
|---|---|
checkin | 用户向仓库提交一次 commit 时。 |
checkout | 用户锁定(签出)一个或多个文件时。 |
activity_summary | 服务器调度器生成周期性活动摘要时(每日 / 每周)。 |
只勾选你的频道需要的项。在大型工作室中,checkout 可能很吵:
许多团队只保留 checkin 和 activity_summary。
自定义 Webhook
使用 custom 类型时,会出现两个额外字段:Custom Headers (JSON)
和 Custom Template (JSON)。它们让你能够对接任何接受 JSON POST 的服务。
Template
模板即发送的 JSON 主体。uVersion 会把双大括号中的变量替换为事件的值。 示例:
{"text": "{{event_type}} par {{username}} dans {{repository}}"}
可用变量:
| 变量 | 内容 |
|---|---|
{{event_type}} | 事件类型(checkin、checkout、activity_summary)。 |
{{repository}} | 仓库名称。 |
{{username}} | 触发事件的用户。 |
{{message}} | commit 消息(用于签入)。 |
{{file_count}} | 涉及的文件数。 |
{{commit_hash}} | commit 哈希。 |
{{timestamp}} | 事件时间戳。 |
Headers
要附加到请求上的 HTTP 头的 JSON 对象,例如一个认证令牌:
{"Authorization": "Bearer VOTRE_JETON"}
默认为 {}(无头)。为传输保留的头
(host、content-length、transfer-encoding、connection)
会被自动剥离,且无法覆盖。
测试、启用、删除
列表中的每个 Webhook 提供以下操作:
- Send test(飞机图标):向服务发送一条测试通知,并就地显示 结果(绿色对勾或叉)。在依赖它之前用于验证 URL 和类型很有用。
- 开关:在不删除的情况下启用 / 停用该 Webhook。
- Edit:修改任意字段。
- Delete:永久删除(需确认)。
安全:SSRF 防护
Webhook 会让 HTTP 请求由服务器发出。为防止恶意 URL 被用来探测 服务器的内部网络(SSRF 攻击),uVersion 在创建、修改以及测试时都会施加严格防护:
- 协议必须是
http或https。任何其他协议都会被拒绝。 - 主机名会经 DNS 解析,并检查得到的每一个 IP 地址。若其中之一指向
非公网地址,则该 Webhook 被拒绝:回环、私有网络(RFC1918)、链路本地、
广播、CGNAT 段
100.64.0.0/10、云元数据169.254.169.254、 ULA / IPv6 链路本地,以及它们的 IPv4-mapped-IPv6 等价物。 - 不跟随 HTTP 重定向(因此指向内部主机的 307 无法绕过防护)。
- 上游的响应主体绝不会返回给客户端(没有 SSRF 预言机)。
实际上:Webhook URL 必须指向一个公网服务(Discord、Slack、Teams,或
你自己可从互联网访问的端点)。指向 localhost、私有 IP
(10.x、192.168.x、172.16-31.x)或内部服务的 URL 会被拒绝,
并给出“Webhook URL refused: …”消息。
常见陷阱
类型与服务不匹配
把 Discord 格式发到 Slack URL(或反之)会产生格式错误的消息,或在服务端被拒绝。 Type 字段必须与 URL 匹配。拿不准时,做一次 Send test。
未勾选任何事件
没有事件的 Webhook 永远不会触发。只要未选中任何事件,客户端就会阻止保存 (“At least one event is required”)。
内部 URL 被拒绝
如果你针对自己机器上或局域网内的服务进行测试,SSRF 防护会拒绝它。请把该服务 暴露在一个公网 URL(或隧道)上,才能将其用作 Webhook 目标。
被遗忘的已停用 Webhook
已停用的 Webhook 仍留在列表中,但不发送任何内容。如果通知安静了下来,请在怀疑 URL 之前,先检查 启用开关。