uVersion
简体中文
下载 →

Wiki

Webhook

按仓库配置的出站通知(Discord、Slack、Teams、custom),在签入和活动摘要时触发。创建、消息格式、模板变量、SSRF 防护。

简介

每当仓库(在服务器上进行版本管理的项目)中发生某个事件时,Webhook 会向外部服务 (Discord、Slack、Microsoft Teams,或你选择的任意 URL)发送一条出站通知。事件是指签入, 或周期性的活动摘要。这是在不打开客户端的情况下让团队保持知情的最简单方式: 当有人提交工作时,一条消息会出现在你的频道里。

Webhook 是按仓库配置的,位于桌面客户端管理面板的 Webhooks 标签页。一个仓库可以有多个 Webhook(例如面向整个团队发往 Discord 的一个, 面向负责人发往私有 Slack 的一个)。

访问权限与角色

Webhook 管理仅限仓库管理员:任意仓库上的超级管理员admin 角色),或所管理仓库上的 project_admin。 其他角色看不到此标签页。

须知 Webhooks 标签页采用多 Webhook 机制(每个仓库可有多个条目)。为兼容起见,服务器端也存在一个 单 URL 的 Discord 通知,但它不会在此处显示:请使用本页介绍的 Webhook。

创建 Webhook

1. 打开 Webhooks 标签页

在管理面板中,先在 PROJECT 行的选择器里选择仓库,然后打开同一行的 Webhooks 标签页:一个 Webhook 属于某个仓库。没有任何 Webhook 的仓库会显示 No webhooks configured

2. 打开表单

点击标签页右上角的 Add WebhookCreate Webhook 窗口会以空白状态打开。

3. 填写字段

有两个必填字段,NameURL,并且必须在 Events 中至少 选择一个事件(它们是可点击的胶囊按钮,而不是下拉列表)。Type 必须与 URL 所指向的服务相匹配。

Create Webhook 窗口:Name 和 URL 字段、Type 下拉菜单(discord、slack、teams、custom),以及选中了 checkin 的 Events 胶囊按钮一行。
字段
Name便于日后辨认的标签(例如 Discord équipe)。必填。
URL目标服务提供的 Webhook URL。必填。被拒绝的 URL 见安全
Typediscordslackteamscustom
Events至少必选一个。实际上:checkinactivity_summary。关于 checkout事件
Enabled启用开关(编辑时以及在列表中可见)。

在 Discord 端获取 URL:频道设置 → 整合 → Webhook → 新建 Webhook → 复制 URL。下面的教程有详细说明。在 Slack 端:在 Slack 应用设置中创建一个 Incoming Webhook。 在 Teams 端:在频道上连接器 → Incoming Webhook

4. 确认,然后发送测试

点击 Create Webhook。Webhook 会以启用状态出现在列表中。在它那一行,点击飞机图标 Send test:uVersion 会向服务发送一条测试通知,并在行尾显示结果——绿色对勾,或带有返回 HTTP 代码的叉。现在就做:这是在依赖此 Webhook 之前确认 URL 和类型正确的唯一方法。

列表中的一行 Webhook:它的开关、名称、discord 类型徽章、事件胶囊按钮、Send test 按钮,以及旁边绿色的结果对勾。

教程:Discord Webhook

这是最常见的情况。“获取 URL”这一步完全在 Discord 内完成,仅需一次。

Discord 端:获取 URL

  1. 打开 Discord 并进入你的服务器。选择(或创建)将接收通知的文字频道,例如 #uversion
  2. 将鼠标悬停在频道名称上,点击齿轮图标(“编辑频道”)。
  3. 在左侧菜单中,打开 整合 标签。
  4. 点击 Webhook,然后点击 新建 Webhook。Discord 会自动创建一个并关联到该频道。
  5. 点击已创建的 Webhook 将其打开。为它取一个名称(例如 uVersion),并确认目标频道正确。头像图片为可选。
  6. 点击 复制 Webhook URL。URL 形如 https://discord.com/api/webhooks/123456789/AbCdEf...
请对此 URL 保密 任何拥有该 URL 的人都能在你的频道中发布消息。不要把它提交到仓库, 也不要公开分享。若发生泄露,请在 Discord 端删除该 Webhook 并重新创建一个。

uVersion 端:接入 URL

按上面的 创建 Webhook 流程,使用以下取值:Name 给自己看的标签 (例如 Discord équipe),URL 你刚复制的那个,Type discord(这样消息才会作为 Discord 嵌入内容发出,必不可少),Events checkin。最后执行 Send test:几秒内应有一条消息出现在 Discord 频道中。

如果测试以 HTTP 401404 状态失败,说明 URL 有误或该 Webhook 已在 Discord 端被删除:请重新复制 URL。如果测试为绿色却什么都没收到,请检查你查看的是否为正确的频道, 以及该 Webhook 是否在 Discord 中被停用。

类型与格式

Type 决定 uVersion 在发送前如何格式化消息。请选择与 URL 所指服务相匹配的类型, 否则消息会以错误的格式到达(或被服务拒绝)。

Type发送的格式
discordDiscord 嵌入内容(标题、颜色、字段)。
slackSlack 载荷(消息块)。
teamsMicrosoft Teams 卡片(MessageCard)。
custom完全由你定义的 JSON 主体:见自定义 Webhook

事件

服务器实际发出的事件有两个:

事件触发时机…
checkin用户向仓库提交一次 commit 时。
activity_summary服务器调度器生成周期性活动摘要时(每日 / 每周)。
checkout:复选框存在,但事件从不发出 表单提供了第三个复选框 checkout,本应用于告知某个文件被锁定(是用户在 修改文件期间对该文件设置的预留)。它已声明但至今从未发出:勾选它不会触发任何通知。 不要依赖它,也不要把它作为唯一选择:只勾选了此事件的 Webhook 将永远保持沉默。

只勾选你的频道需要的项。实际上,有用的组合是用于团队工作流的 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}}事件类型(checkinactivity_summary)。
{{repository}}仓库名称。
{{username}}触发事件的用户。
{{message}}commit 消息(用于签入)。
{{file_count}}涉及的文件数。
{{commit_hash}}commit 哈希。
{{timestamp}}事件时间戳。

Headers

要附加到请求上的 HTTP 头的 JSON 对象,例如一个认证令牌:

{"Authorization": "Bearer VOTRE_JETON"}

默认为 {}(无头)。为传输保留的头 (hostcontent-lengthtransfer-encodingconnection) 会被自动剥离,且无法覆盖。

必须为有效 JSON Headers 和 Template 字段在保存时会被校验。无效的 JSON 会阻止保存, 并给出明确消息(“Invalid JSON in headers” /“… template”)。请检查你的大括号和引号。

测试、启用、删除

列表中的每个 Webhook 提供以下操作:

  • Send test(飞机图标):向服务发送一条测试通知,并就地显示 结果(绿色对勾或叉)。在依赖它之前用于验证 URL 和类型很有用。
  • 开关:在不删除的情况下启用 / 停用该 Webhook。
  • Edit:修改任意字段。
  • Delete:永久删除(需确认)。
测试不会返回响应主体 失败时,uVersion 只显示服务返回的 HTTP 状态(例如“Webhook returned HTTP 404”), 绝不返回响应内容。这是有意为之(见安全)。如果测试失败,请先检查 URL 和 类型,然后检查服务端该 Webhook 的权限。

安全:SSRF 防护

Webhook 会让 HTTP 请求由服务器发出。为防止恶意 URL 被用来探测 服务器的内部网络(SSRF 攻击),uVersion 在创建、修改以及测试时都会施加严格防护:

  • 协议必须是 httphttps。任何其他协议都会被拒绝。
  • 主机名会经 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.x192.168.x172.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 之前,先检查 启用开关。