跳转到主要内容
当您连接 Azure DevOps 项目时,Kody 通常会自动创建 webhook。本页面介绍手动设置路径 — 当自动注册没有发生时使用,通常在自托管安装或 Kody 无法代表您创建服务钩子的 Azure 项目中。
Webhook URL 必须能到达 Webhooks 服务(端口 3332)。仅当您的反向代理将 /.../webhook 路径转发到 Webhooks 服务时,才能使用 API 域名。

Azure Repos webhook URL 需要签名令牌

与 GitHub、GitLab、Bitbucket 和 Forgejo 不同,Azure Repos webhook 请求必须包含加密的 token 查询参数。Kodus 对每个到达的请求验证此令牌,没有令牌的调用会被 403 Unauthorized 拒绝。该令牌由您在自托管设置中已配置的两个环境变量派生:
  • CODE_MANAGEMENT_SECRET — 32 字节的加密密钥(十六进制编码)。
  • CODE_MANAGEMENT_WEBHOOK_TOKEN — 密钥加密的明文。
所以 Azure webhook URL 形式如下:
https://kodus-api.yourdomain.com/azure-repos/webhook?token=<generated>
<generated> 值由使用 AES-256-CBC 将 CODE_MANAGEMENT_WEBHOOK_TOKENCODE_MANAGEMENT_SECRET 加密产生,格式为 <ivHex>:<cipherHex>
当 Kody 通过 UI 驱动的集成流程为您创建 webhook 时,会自动生成此令牌。仅当您在 Azure DevOps 中手动注册 webhook 时,才需要手动生成。

生成 webhook 令牌

选择适合您环境的选项。两个选项都使用您的 Kodus 堆栈已配置的环境变量 — 您不需要克隆代码库。

选项 A — 在运行中的 Kodus 容器内(推荐)

对已运行的 api 容器执行。环境变量已经在作用域内:
docker compose exec api node -e "
const crypto = require('crypto');
const key = Buffer.from(process.env.CODE_MANAGEMENT_SECRET, 'hex');
const iv = crypto.randomBytes(16);
const c = crypto.createCipheriv('aes-256-cbc', key, iv);
let e = c.update(process.env.CODE_MANAGEMENT_WEBHOOK_TOKEN, 'utf8', 'hex');
e += c.final('hex');
console.log(iv.toString('hex') + ':' + e);
"
输出就是您粘贴到 webhook URL 上作为 ?token=... 的值。示例:
8f3c1a4b9e2d6f8a1c3e5f7091a4b7c2:d1e9a23c78...

选项 B — 本地使用 Node(无 Docker)

如果您的 Kodus 堆栈未运行,或您想在另一台机器上生成令牌,导出两个环境变量后运行:
export CODE_MANAGEMENT_SECRET="<与您的 .env 相同的值>"
export CODE_MANAGEMENT_WEBHOOK_TOKEN="<与您的 .env 相同的值>"

node -e "
const crypto = require('crypto');
const key = Buffer.from(process.env.CODE_MANAGEMENT_SECRET, 'hex');
const iv = crypto.randomBytes(16);
const c = crypto.createCipheriv('aes-256-cbc', key, iv);
let e = c.update(process.env.CODE_MANAGEMENT_WEBHOOK_TOKEN, 'utf8', 'hex');
e += c.final('hex');
console.log(iv.toString('hex') + ':' + e);
"
两个环境变量的值必须与您的 Kodus API 容器正在使用的完全一致。密钥不匹配会产生看起来有效但 Kodus 会以 403 Unauthorized 拒绝的令牌。
令牌不会过期 — 您可以在您组织的每个 Azure Repos webhook 上重复使用同一个生成的值。仅在轮换 CODE_MANAGEMENT_SECRETCODE_MANAGEMENT_WEBHOOK_TOKEN 时才需要重新生成。

在 Azure DevOps 中创建 webhook 订阅

  1. 导航到您的 Azure DevOps 项目。
  2. 单击左下角的项目设置
  3. 常规下,选择服务钩子
  4. 单击 + 创建订阅
  5. 配置 webhook:
    • 服务: Web Hooks
    • 在此类型的事件上触发: 选择一个受支持的事件(见下文)
    • URL: 您的 Kodus Azure Repos webhook URL,附加令牌:
      https://kodus-api.yourdomain.com/azure-repos/webhook?token=<generated>
      
    • 过滤器(可选):如果需要,按仓库或分支过滤。
    • 操作: 向给定的 URL 发送 POST 请求。
  6. 单击完成
每个事件类型需要创建一个订阅。Kodus 当前响应:
  • git.pullrequest.created — 拉取请求已创建
  • git.pullrequest.updated — 拉取请求已更新
  • git.pullrequest.merge.attempted — 拉取请求合并已尝试
  • ms.vss-code.git-pullrequest-comment-event — 拉取请求已评论
确保该 URL 可以从 Azure DevOps 访问,并在端口 3332 上(直接或通过您的反向代理)接受到达的 POST 请求。

故障排查

?token= 值缺失、被截断,或者用与运行中 API 使用的不同的 CODE_MANAGEMENT_SECRET / CODE_MANAGEMENT_WEBHOOK_TOKEN 生成。使用选项 A 重新生成令牌(保证使用容器实际使用的环境变量产生),并在 Azure 中更新订阅 URL。
Azure DevOps 对失败的投递重试次数有限。查看服务钩子页面 — 成功的投递会显示绿色勾号。如果投递因连接错误失败,验证 URL 从公网可达,并且您的反向代理将 /.../webhook 路径转发到端口 3332。
每个事件类型在 Azure DevOps 中需要自己的订阅。如果您只创建了”拉取请求已创建”,更新和评论将不会触发审查。