Files
EP-Hub-Skill/.dingtalk/README.md
T

8.7 KiB
Raw Permalink Blame History

Hub 钉钉通知接入

这套封装只帮助 Hub 向项目群发送进度、异常摘要和负责人提醒,不是 Etunel 任务通道,也不负责审批、阶段门禁或项目留档。仅更新此仓库不会部署到实际项目;由部署负责人明确安装,成员 Agent 不调用。

文件与依赖

依赖 Python 3.9+,不需要第三方 Python 包、jq 或 Bash 才能在 Windows 运行。PowerShell 入口要求 7.3+;也可直接运行 Python。macOS/Linux 保留 Shell 入口。

真实发送需要 官方 DingTalk Workspace CLI 的原生可执行文件。按官方安装说明选择系统版本;Windows 使用 dws.exe,不要把 npm/Bun 的 dws.cmd 或 dws.bat 当原生程序。可以把原生文件加入 Hub 进程的 PATH,或在项目配置的 DINGTALK_PROGRESS_DWS_PATH 填它的绝对路径。本仓库不保存二进制,不自动安装、登录或更新全局 Skills。

部署后检查 python --version(macOS/Linux 可用 python3)及原生 dws version。所用 DWS 需支持 api --data - 从标准输入读 JSON;正文、群参数不放命令行,密钥仅临时注入子进程环境。更换 DWS 版本后由部署负责人核对兼容性,离线预览不证明真实接口可用。

部署到 Hub 项目

将共用 Python 文件和需要的平台入口一起放入目标项目的 scripts/,不要只复制一个入口。重试逻辑已合入共用实现,无需复制源项目的 dingtalk-dns-retry.sh。保持下列布局:

目标项目/
├── scripts/
│   ├── dingtalk_notify.py
│   ├── dingtalk-progress
│   ├── dingtalk-bot-message
│   ├── dingtalk-progress.ps1
│   └── dingtalk-bot-message.ps1
└── .dingtalk/
    └── config.env

由部署负责人从 配置示例 新建实际配置,别覆盖已有有效配置:

  • UTF-8,可带 BOM,支持 Windows CRLF 和 LF;值按字面解析,不执行 Shell、不展开变量,不加 Shell 引号。
  • 初始保持 ENABLED=0、DRY_RUN=1(实际字段均有 DINGTALK_PROGRESS_ 前缀)。
  • 配置包括应用、机器人、目标群、项目名称、开关及机器人密钥。机器人必须属于配置的应用,已经加入目标群,并具备企业内机器人发送消息权限(qyapi_robot_sendmsg);脚本不自动加群或申请权限。
  • macOS/Linux 对实际配置执行 chmod 600 .dingtalk/config.env;接受 400 或 600。Windows 不以 Unix 权限位作门槛,由部署负责人用 NTFS 权限限制其他用户读取或修改配置。
  • 实际配置必须被目标项目的 Git 忽略。不要把它、真实凭据或内部标识回传给 AI 会话或提交仓库。

路径与当前工作目录无关:配置总从 Python 脚本所在项目根目录读取。消息的 --file 路径则相对当前工作目录解析。

凭据:所有系统统一读取配置

普通进度发送使用内部应用身份,不需要用户 OAuth 登录。Windows、macOS、Linux 只从本地 .dingtalk/config.env 的 DINGTALK_PROGRESS_CLIENT_SECRET 读取机器人密钥,不再从 DING_SEC、其他环境变量或 macOS 钥匙串回退取值。

由部署负责人在本地编辑器中填写该字段,保持单行字面值,不加 Shell 引号;不要在会话、命令历史或仓库示例里填写真实值。密钥为空或字段缺失时,真实发送停止并提示负责人补配置;离线预览不要求填写密钥。

脚本仅在发送时把该值临时注入 DWS 子进程的 DWS_CLIENT_SECRET,同时注入配置中的 DWS_CLIENT_ID。这只是脚本内部对接 DWS 的方式,不需要负责人再配置环境变量。密钥不进入命令参数、消息正文、预览或错误输出;人员搜索进程也不会取得机器人密钥。

实际 config.env 现在包含明文密钥:macOS/Linux 设为 400 或 600;Windows 通过文件“属性 → 安全”限制为 Hub 运行账号及必要管理员可访问,不放在公共共享目录。目标项目必须忽略实际配置及其备份,只提交空值示例。不要把配置文件用作 --file 正文、成果或通知附件。

从旧配置迁移

  1. 更新共用 Python 脚本及需要的平台入口。
  2. 由部署负责人在本地配置补填 DINGTALK_PROGRESS_CLIENT_SECRET;删除旧的 DINGTALK_PROGRESS_KEYCHAIN_SERVICE 字段。
  3. 检查文件权限与 Git 忽略,再做离线预览;正式发送仍需要启用开关、正确的应用权限和目标群。
  4. 旧环境变量与钥匙串不再被脚本读取;本次改动不会删除其中原有内容。

脚本每次调用重新读取本地配置,不再因为密钥配置依赖 Hub 继承某个终端的环境变量;Python、dws 路径及按姓名查询所需的 DWS 登录仍须对实际运行 Hub 的操作系统账号可用。

可选的按姓名提醒

--at 会调用 DWS 人员搜索,和应用机器人发送是不同的认证需求。只有使用按姓名提醒时,部署负责人需要:

  1. 在 DWS 中登录需要使用的组织账号;
  2. 将已确认的稳定 profile 填入 DINGTALK_PROGRESS_PROFILE;
  3. 确认该账号、机器人应用、目标群属于同一组织,且账号允许查询人员。

脚本在搜索和发送中传入同一个 profile,不自动选择或切换账号;应用归属与群归属仍需部署负责人核对,脚本不能仅凭 profile 字符串证明二者一致。查询只接受完整姓名的唯一匹配;查不到、重名、权限不足或返回结构不支持时整条提醒停止,不默认选择第一个,也不静默删掉 @ 后发送。

--at-id 和 --group 保留源脚本兼容能力,仅用于已有真实映射或用户明确指定的目标;不让 AI 猜编号或在群之间试发。普通进度通知不需要配置人员账号。

先做离线预览

在目标项目根目录选一种入口。以下命令只预览,不联网,不需要 dws,不查通讯录、不使用密钥认证。已有配置会在本地读取,但密钥不会输出:

python scripts/dingtalk_notify.py progress milestone '本阶段成果已确认并归档,下一步安排联调。' --dry-run
./scripts/dingtalk-bot-message.ps1 --title '需要补充接口说明' --text '请接口负责人补齐返回值说明,并回自己的角色会话同步结果。' --dry-run

macOS/Linux 等价命令:

sh scripts/dingtalk-progress milestone '本阶段成果已确认并归档,下一步安排联调。' --dry-run
sh scripts/dingtalk-bot-message --title '需要补充接口说明' --text '请接口负责人补齐返回值说明,并回自己的角色会话同步结果。' --dry-run

两种入口都遵守配置的 DRY_RUN=1,显式 --dry-run 不能被配置取消。即使没有配置,也能显式预览正文;此时不表示项目配置可用。正文支持中文多行 Markdown;复杂正文建议先保存 UTF-8 文件,用 --file 代替内联摘要或 --text,它不是附件上传。

确认部署与发送授权后,负责人再将 ENABLED=1 且 DRY_RUN=0。仓库维护测试不能用真实发送作冒烟测试。实际 Hub 的事件判断、参数示例和结果含义见 通知规则 和 脚本用法。

失败处理与测试

仅明确的 DNS 解析失败每隔 10 秒重试,总计最多 3 次;已获有效回执即停止。认证、权限、未知错误不重试;超时或缺少回执不盲目重发。单次 DWS 调用超时 60 秒;本次结束后由 Hub 说明,不在外层循环重试。只输出安全摘要和发送回执,不输出原始请求或错误日志。

本封装不建消息队列、计划任务、重发历史或通知状态库;避免重复事件仍由 Hub 利用已有项目留档判断,不重造 Etunel 软件机制。

python -X utf8 scripts/test_dingtalk_notify.py

测试仅在临时目录使用假配置、假密钥和模拟 DWS;同时检查当前系统可用的 PowerShell/Shell 入口,不访问真实项目配置。覆盖配置密钥为唯一来源、密钥不回显、不通过命令参数传递以及预览不认证,不等于完成真实钉钉发送验收。