
Codex 接 GitHub:从 0 搭一个会私聊你的「仓库监控机器人」
最近同时在做几个团队协作项目,我越来越受不了 GitHub 的通知方式。
Issue 开了半天,我刷仓库时才发现。PR 已经等着 Review,群里没人提,进度就卡在那里。可把所有提醒全部打开,评论、机器人更新和代码同步又会把重要消息淹掉。
所以我想要一个值班机器人:GitHub 出现需要处理的事情,它直接在飞书里私聊我。

先说清楚,这次接的不是“飞书群自定义机器人 Webhook”。你要创建一个企业自建应用,打开它的机器人能力,让 GitHub Actions 以这个机器人的身份发送消息。
最后你会得到这条链路:
https://github.com/new我不会写代码,但这篇文章里会有完整代码。你只需要照着创建应用、开权限、复制文件和验证结果;遇到报错,再把截图交给 Codex。
name: Repo Monitor
on:
issues:
types: [opened, reopened]
pull_request_target:
types: [opened, reopened, ready_for_review, review_requested]
release:
types: [published]
workflow_dispatch:
permissions:
contents: read
issues: read
pull-requests: read
jobs:
notify:
runs-on: ubuntu-latest
timeout-minutes: 3
steps:
- name: Build notification text
id: message
shell: bash
env:
EVENT_NAME: ${{ github.event_name }}
REPOSITORY: ${{ github.repository }}
run: |
case "$EVENT_NAME" in
issues)
title=$(jq -r '.issue.title' "$GITHUB_EVENT_PATH")
url=$(jq -r '.issue.html_url' "$GITHUB_EVENT_PATH")
text="💡 新 Issue|$REPOSITORY\n$title\n$url"
;;
pull_request_target)
title=$(jq -r '.pull_request.title' "$GITHUB_EVENT_PATH")
url=$(jq -r '.pull_request.html_url' "$GITHUB_EVENT_PATH")
text="🔀 PR 需要关注|$REPOSITORY\n$title\n$url"
;;
release)
title=$(jq -r '.release.name // .release.tag_name' "$GITHUB_EVENT_PATH")
url=$(jq -r '.release.html_url' "$GITHUB_EVENT_PATH")
text="🚀 新 Release|$REPOSITORY\n$title\n$url"
;;
*)
text="🧪 测试成功|$REPOSITORY 的监控机器人已连通"
;;
esac
{
echo 'text<<EOF'
printf '%b\n' "$text"
echo 'EOF'
} >> "$GITHUB_OUTPUT"
- name: Send as Feishu bot
shell: bash
env:
FEISHU_APP_ID: ${{ secrets.FEISHU_APP_ID }}
FEISHU_APP_SECRET: ${{ secrets.FEISHU_APP_SECRET }}
FEISHU_RECEIVE_ID: ${{ secrets.FEISHU_RECEIVE_ID }}
MESSAGE_TEXT: ${{ steps.message.outputs.text }}
run: |
for name in FEISHU_APP_ID FEISHU_APP_SECRET FEISHU_RECEIVE_ID; do
if [ -z "${!name}" ]; then
echo "缺少 $name,请先添加 Repository secret。"
exit 1
fi
done
token_body=$(jq -n \
--arg app_id "$FEISHU_APP_ID" \
--arg app_secret "$FEISHU_APP_SECRET" \
'{app_id:$app_id,app_secret:$app_secret}')
token_response=$(curl --silent --show-error \
--retry 3 \
--retry-all-errors \
--header "Content-Type: application/json" \
--data "$token_body" \
"https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal")
if [ "$(jq -r '.code // -1' <<< "$token_response")" != "0" ]; then
echo "获取 tenant_access_token 失败:$(jq -r '.msg // "unknown error"' <<< "$token_response")"
exit 1
fi
tenant_token=$(jq -r '.tenant_access_token // empty' <<< "$token_response")
if [ -z "$tenant_token" ]; then
echo "飞书没有返回 tenant_access_token。"
exit 1
fi
content=$(jq -nc --arg text "$MESSAGE_TEXT" '{text:$text}')
message_body=$(jq -n \
--arg receive_id "$FEISHU_RECEIVE_ID" \
--arg content "$content" \
'{receive_id:$receive_id,msg_type:"text",content:$content}')
http_code=$(curl --silent --show-error \
--output response.json \
--write-out "%{http_code}" \
--retry 3 \
--retry-all-errors \
--header "Authorization: Bearer $tenant_token" \
--header "Content-Type: application/json" \
--data "$message_body" \
"https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=open_id")
if [ "$http_code" != "200" ]; then
echo "飞书发送接口返回 HTTP $http_code。"
exit 1
fi
if [ "$(jq -r '.code // -1' response.json)" != "0" ]; then
echo "机器人发送失败:$(jq -r '.msg // "unknown error"' response.json)"
exit 1
fi
echo "飞书机器人通知发送成功。"
一、先决定监控什么,通知到哪
第一版只回答两个问题。
监控什么?
- Issue:新建或重新打开;
- PR:新建、重新打开、进入可审核状态、请求 Review;
- Release:正式发布;
- 手动测试:自己点击一次,确认机器人能收到消息。
通知到哪?
通知由飞书应用机器人发送给指定用户。文章默认发给你自己,所以需要拿到你在这个应用下的 open_id。

这里有个很容易踩的坑:同一个人在不同飞书应用下的 open_id 可能不同。你不能随便从另一个应用或另一套 CLI 配置里复制一个 ou_ 开头的 ID。
第一版先做只读监控。权限分三档:

A 档跑稳之后,再考虑 needs-info、自动打标签和过滤 Bot。自动合并 PR、关闭 Issue、修改代码继续交给人判断。
二、最小可跑配置
整个机器人需要五样东西:
- 一个 GitHub 测试仓库;
- 一个飞书企业自建应用;
- 应用的机器人能力;
- 发送消息权限 im:message:send_as_bot;
- 三个 GitHub Secrets:FEISHU_APP_ID、FEISHU_APP_SECRET、FEISHU_RECEIVE_ID。
GitHub 工作流只开三项读取权限:
FEISHU_APP_ID
FEISHU_APP_SECRET
FEISHU_RECEIVE_ID
机器人只能看事件并发送飞书消息,不能修改仓库、关闭 Issue 或合并 PR。

三、飞书部分只做三件事
飞书这边不用钻进所有菜单。你只需要让一个企业自建应用具备“以机器人身份发消息”的能力。
打开 飞书开发者后台,按下面三步做:
- 创建企业自建应用,名称可以填 GitHub 仓库监控。
- 添加“机器人”能力,在权限管理中开通 im:message:send_as_bot。
- 创建并发布一个版本,可用范围先只选你自己。
Add GitHub repository monitor
发布后,在飞书搜索这个机器人。能找到它,并且你在可用范围内,这部分就完成了。
接下来只拿走三个值:
- App ID:基础信息 → 凭证与基础信息;
- App Secret:和 App ID 在同一页;
- 你的 open_id:在“发送消息”API 调试台中,把 receive_id_type 设为 open_id,选择自己后复制 ou_...。[4]
这是一条用于教程实测的 Issue。
验证目标:
- 创建 Issue 后自动触发 GitHub Actions
- 飞书应用机器人收到私聊通知
open_id 属于具体应用,别从另一个飞书应用复制。App Secret 直接存进 GitHub,不要发到聊天里,不要写进代码,截图前也要确认它已隐藏。
飞书部分的完成标准:机器人已发布,你拿到 App ID、App Secret 和 open_id。
四、GitHub Step 1:建一个测试仓库
打开 GitHub 新建仓库页。仓库名填 repo-monitor-demo,公开或私有都可以。第一次建议勾选 Add a README file,这样创建后会直接有 main 分支。
点击 Create repository后,你应该看到仓库首页。

先认清顶部四个入口:
- Code:存放工作流文件;
- Issues:最后创建真实测试事件;
- Actions:看工作流是否运行成功;
- Settings:保存飞书凭证。

如果找不到 Issues,打开 Settings → General → Features,勾选 Issues。Actions 默认可用,这一版不需要改 Workflow permissions。
完成标准:仓库有 main 分支,并能看到 Issues、Actions 和 Settings。
五、GitHub Step 2:把三项配置存进 Secrets
进入测试仓库,按这条路径打开凭证页:
Settings → Secrets and variables → Actions → New repository secret
依次创建三个 Secret:
请把当前 GitHub → 飞书监控机器人升级成“人工确认后执行”的版本。
要求:
1. 机器人可以自动读取 Issue、PR 和 Release 上下文;
2. 自动生成处理建议和准备执行的 GitHub 动作;
3. 先把建议发送到飞书,展示“确认执行 / 修改 / 跳过”;
4. 只有收到我的确认,才允许评论、打标签、分配负责人或创建 Draft Release;
5. 每次执行后,把操作结果和 GitHub 链接发回飞书;
6. 默认禁止自动合并 PR、关闭 Issue、删除内容和修改代码;
7. 为每类写入操作单独配置最小 GitHub 权限,并记录审计日志。
请先给出权限清单、确认流程和安全边界,再生成完整代码。
它们对应的值分别是 App ID、App Secret 和刚才复制的 ou_...

每一项都要点一次 New repository secret,在 Name 填上面的名字,在 Secret 粘贴对应的值,再点 Add secret。名字必须完全一致,不要加引号,不要在前后多粘贴空格。
完成标准:Secrets 列表里能看到三个名称,但看不到具体值。GitHub 保存后不允许回读 Secret;如果怀疑填错,直接点进去更新。
六、GitHub Step 3:创建工作流文件
回到仓库首页,点击:
Add file → Create new file
文件名填写:

这个路径要从第一个点开始完整输入。.github 是 GitHub 的配置目录,workflows 用来存放自动化任务,.yml 是工作流文件格式。

完成标准:编辑器顶部显示的路径正好是 .github/workflows/repo-monitor.yml。
七、GitHub Step 4:粘贴完整代码
把下面代码从 name: Repo Monitor 开始完整复制,粘贴进右侧编辑器。不要手动调整空格;YAML 对缩进很敏感。
我在搭 GitHub → 飞书应用机器人监控。
请检查这份 repo-monitor.yml:
1. GitHub Actions YAML 缩进;
2. App ID / App Secret 换取 tenant_access_token 的请求;
3. receive_id_type=open_id;
4. 飞书消息 content 是否被正确转成 JSON 字符串;
5. 日志是否会泄露 Secret 或 Token。
请给我完整可替换版本,不要省略代码。

这份代码分成两段。第一段把 GitHub 事件整理成中文消息;第二段获取短期 Token,再调用飞书发送消息接口。它不会输出 App Secret 或 tenant_access_token。
如果复制后出现错误,可以把工作流和报错截图发给 Codex:
permissions:
contents: read
issues: read
pull-requests: read
八、GitHub Step 5:提交工作流
检查文件名和代码都完整后,点击页面右上角的 Commit changes…。
在弹窗中把提交说明写成:
监控什么:Issue / PR / Release
通知到哪:飞书应用机器人私聊指定用户
自己的测试仓库可以直接提交到 main。如果你在团队正式仓库里操作,就新建分支并走 PR 审核。
GitHub Issue / PR / Release
↓
GitHub Actions 自动运行
↓
飞书应用机器人
↓
机器人私聊指定用户
提交后回到 Code 页,确认能看到 .github/workflows/repo-monitor.yml;再打开 Actions,左侧应该出现 Repo Monitor。
九、GitHub Step 6:先手动跑一次
进入仓库顶部的 Actions,左侧点击 Repo Monitor,然后点击:
Run workflow → Run workflow
等待十几秒并刷新页面。你应该同时看到两个结果:
- GitHub Actions 出现绿色对勾;
- 飞书里的“Punk的小P”(或你给应用起的名字)私聊你:“测试成功”。
.github/workflows/repo-monitor.yml
飞书里收到“测试成功”,说明 App ID、App Secret、open_id 和消息权限都能正常工作。手动测试只负责检查连通性;接下来再验证实际的 Issue 事件。
如果 Actions 出现红叉,点进失败步骤查看错误:
- 缺少 FEISHU_...:GitHub Secret 名字或值有问题;
- 获取 tenant_access_token 失败:App ID / App Secret 不匹配;
- Bot has NO availability to this user:你不在应用可用范围,或还没有和机器人建立会话;
- receive_id invalid:拿错了其他应用的 open_id;
- 99991672 / permission denied:发送消息权限没有开通或版本还没发布。
十、GitHub Step 7:创建一条真实 Issue
打开:
Issues → New issue
我这次实测使用的标题是:
测试:GitHub Issue 是否会触发飞书监控
正文可以写:

点击 Submit new issue。提交后不要再手动点 Run workflow,这次要验证 Issue 能否自动触发。
我这次实测创建的是 Issue #1,截图如下。读者不需要打开我的仓库,只要在自己的仓库完成同样操作。
十一、检查 Actions 是否由 Issue 自动触发
打开 Actions → Repo Monitor,点进刚出现的运行记录。依次核对四个位置:
- 页面写着 Triggered via issue;
- 事件显示 on: issues;
- 状态是 Success;
- notify 任务是绿色对勾。
这次真实 Issue 产生的 Actions 运行记录已成功完成,截图中的触发来源、事件名称和任务状态都能对应上。

十二、看飞书最终收到什么
Actions 成功后,打开飞书里的应用机器人私聊。实际收到的内容是:


这张图是这次实测的飞书结果,保留了机器人名称和最新消息。看到 GitHub Issue、自动运行记录和飞书消息三处内容一致,整条链路才算验证完成。
到这里,第一版已经跑通。你可以继续创建测试 PR 或 Release,检查另外两种通知。

十三、三个必须提前知道的坑
1. 权限
GitHub 保持只读,飞书只开 im:message:send_as_bot。如果以后要让机器人自动评论 Issue,再单独增加 issues: write,不要顺手开 write-all。
pull_request_target 可以让 Fork PR 触发通知,但这条工作流里不能检出并运行外部 PR 的代码。它持有飞书 App Secret,一旦运行不可信代码,凭证就可能泄露。
2. Rate limit
飞书发送消息接口当前限制为 1000 次/分钟、50 次/秒。[5] 第一版的 Issue / PR / Release 通常很难触发上限。
更常见的问题是误报。每次编辑、加标签、推送代码都通知,机器人很快会被你自己静音。
3. open_id 和可用范围
open_id 属于具体应用,应用可用范围又决定机器人能联系谁。ID 正确但用户不在可用范围里,消息仍然会失败。
https://x.com/@AdrianPunk115第一版守住一句话:收到通知后需要有人采取行动,这条消息才应该出现。
十四、下一版:机器人先准备,我只负责确认
现在这版机器人只读 GitHub,然后把重要事件私聊给我。它已经能解决漏看问题,但收到消息之后,我还要自己打开仓库、判断情况、组织回复。
所以,还是太麻烦。
我又做了升级,把它升级成一个“带确认按钮的执行助手”。机器人先完成信息收集、判断和草稿,涉及修改 GitHub 的动作,再回到飞书等我确认。


它可以先从三类任务开始:
- Issue 缺少复现步骤:自动整理缺失项,起草追问内容;我确认后发表评论并添加 needs-info。
- PR 等待 Review:自动总结改动、测试结果和风险;我确认后分配 Reviewer 或发布评论。
- 准备发 Release:自动汇总已经合并的 PR,生成 Release Notes 草稿;我确认后创建 Draft Release。
给 Codex 的下一版指令也可以直接复制:

这一步会增加 GitHub 写权限、飞书交互卡片回调和一个可接收确认事件的服务。先把本文的只读版本跑稳,再逐项开放能力;每增加一种写入动作,都要单独检查权限和撤销方式。
机器人负责准备和执行,我保留最后一次确认。
最后
整个过程可以压缩成两句话:
💡 新 Issue|adrianpunk/repo-monitor-demo
测试:GitHub Issue 是否会触发飞书监控
https://github.com/adrianpunk/repo-monitor-demo/issues/1
你负责选择事件、控制权限、保存凭证和验证结果。Codex 负责写代码、读日志、修错误,并继续增加过滤规则。等下一版接上确认流程后,大部分重复处理可以交给机器人,你只需要判断“要不要执行”。
你最想先监控 Issue、PR 还是 Release?
关于作者
Punk|中科大管理学硕士|AI提示词、AI小白教程|Punk系列Skills作者|3个月赚了8位数|Learn in Public|FDE文章浏览量240w|@AdrianPunk115