让组织级(
/orgs/{org}/discussions/)Discussion 创建后能实时触发 CSM-QA-Bot, 而不必等待 30 分钟一次的定时扫描。
组织 Discussion 创建 / 追问
│
▼
GitHub App Webhook (event: discussion.created / discussion_comment.created)
│ (HTTPS POST, X-Hub-Signature-256)
▼
Cloudflare Worker (cloudflare-worker.js)
│ 1. 验签
│ 2. 过滤 Bot 自身评论(含防重标记且 sender/comment.user type 为 Bot),防止无限循环
│ 3. 用 App 私钥签 JWT
│ 4. 拿 installation access token
│ 5. POST /repos/<owner>/<repo>/dispatches
│ event_type: "org_discussion_created"
│ client_payload: { discussion_number: <N> }
▼
GitHub Actions (csm-discussion-bot.yml on: repository_dispatch)
│
▼
scripts/discussion_bot.py --org-discussion-number <N>
定时扫描 (schedule: */30 * * * *) 仍保留作兜底,确保 webhook 偶发漏发时不会丢消息。
- 打开
https://github.com/organizations/<你的组织>/settings/apps/new - 配置:
- App name:
CSM-QA-Bot-Webhook-Relay(任意) - Homepage URL:本仓库 URL
- Webhook URL:先留空或随便填,部署完 Worker 后再回来更新
- Webhook secret:用
openssl rand -hex 32生成强随机字符串,记下来
- App name:
- Repository permissions:
- Contents:
Read-only(用于触发 dispatches API) - 或 Metadata:
Read-only(必选,所有 App 默认包含)
- Contents:
- Organization permissions:
- Discussions:
Read & write
- Discussions:
- Subscribe to events 勾选:
Discussion和Discussion comment - 创建后:
- 记下 App ID(在 App 设置页顶部的数字)
- 滚动到 "Private keys" 区,点 Generate a private key,下载
.pem文件
在 App 设置页 → 左侧 Install App → 选择目标组织 → 选择 "All repositories"
或仅勾选 .github(即托管 csm-discussion-bot.yml 工作流的仓库)。
GitHub 下发的私钥是 PKCS#1(-----BEGIN RSA PRIVATE KEY-----),
而 Cloudflare Worker 的 Web Crypto API 只接受 PKCS#8:
openssl pkcs8 -topk8 -nocrypt \
-in csm-qa-bot-webhook-relay.<date>.private-key.pem \
-out app.pkcs8.pem转换后开头应是 -----BEGIN PRIVATE KEY-----。
cd webhook
npm install -g wrangler # 已装可跳过
wrangler login # 浏览器登录 Cloudflare 账号
# 注入三个 secret(命令会进入交互式输入)
wrangler secret put WEBHOOK_SECRET # 粘贴步骤 1 生成的 webhook secret
wrangler secret put GITHUB_APP_ID # 粘贴步骤 1 的 App ID
wrangler secret put GITHUB_APP_PRIVATE_KEY # 粘贴 app.pkcs8.pem 全文(含 BEGIN/END 行)
wrangler deploy部署完成后 wrangler 会输出 Worker URL,类似
https://csm-qa-bot-webhook-relay.<你的子域>.workers.dev。
回到 App 设置页 → Webhook URL 改为上一步拿到的 Worker URL → 保存。
然后在 App 设置页 → Advanced → Recent Deliveries 里点
"Redeliver" 触发一次 ping,看 Worker 是否返回 200 pong,并通过响应体确认验签通过。
csm-discussion-bot.yml 仍使用现有的两项 secrets,无需为 webhook 新增:
| Secret | 用途 |
|---|---|
CSM_QA_GH_TOKEN |
GitHub Fine-grained PAT,用于 GraphQL 读写 Discussions 以及 Actions checkout。仅需授权 <org>/.github 仓库(既是工作流宿主,也是组织级 Q&A discussions 的实际归属),权限:Discussions: Read & Write、Contents: Read。如组织级 discussions 实际归属其他仓库,请同步设置 workflow 的 DISCUSSION_SOURCE_REPO 环境变量。 |
LLM_API_KEY |
DeepSeek / 其他 LLM key |
Worker 的三个 secret(
WEBHOOK_SECRET/GITHUB_APP_ID/GITHUB_APP_PRIVATE_KEY) 是 Cloudflare Worker 的 secret,不是仓库 Actions secret。
- 在组织级 Q&A 分类下随便发一条新 Discussion。
- Cloudflare Dashboard → Workers → csm-qa-bot-webhook-relay → Logs:
应能看到
202 {"ok":true,"discussion_number":N}。 - GitHub App → Advanced → Recent Deliveries:应显示 ✅ 200。
- 本仓库 → Actions → CSM Q&A Discussion Bot:应在 ~10 秒内出现一次
repository_dispatch触发的运行。 - 等待几分钟后回到 Discussion 页面,应看到 Bot 评论。
- 在 Bot 评论下方追问(发新评论),应再次触发一次
repository_dispatch运行并收到回复。 Bot 自身发布评论触发的 webhook 会被 Worker 自动过滤,不会产生额外运行。
| 现象 | 原因 / 处理 |
|---|---|
Worker 返回 401 Invalid signature |
WEBHOOK_SECRET 与 GitHub App 中配置不一致 |
Worker 返回 500 App auth failed |
私钥未转 PKCS#8,或 GITHUB_APP_ID 错误,或 App 未安装到该 repo |
Worker 返回 502 Dispatch failed: HTTP 404 |
App 安装时未授权访问该 repo / Contents 权限不足 |
Worker 返回 200 Ignored event |
收到了非 discussion/discussion_comment 事件(正常,过滤掉了) |
Worker 返回 200 Ignored: bot comment |
Bot 自身发布评论后触发的 webhook,已正确过滤 |
Actions 中触发了但 step 报 client_payload.discussion_number 为空 |
Worker 端 payload 解析失败,检查 Worker 日志 |
| Discussion 已创建但 30 分钟内无回复 | Webhook 链路异常,定时扫描会兜底处理 |