步骤一:安装、网关 daemon、令牌与健康检查
Node 使用 22.16+ 或 24 LTS(以 docs.openclaw.ai 为准)。安装 CLI 后务必执行 openclaw doctor,确认 TLS、企业代理与 PATH 在非交互环境下也成立。
网关监听建议绑定 127.0.0.1,由 SSH 反向隧道或内网反代把 CI 厂商的 Webhook delivery 转到本机路径;Dashboard 令牌写入 plist、env 文件或 Keychain,权限收紧到运行网关的账户只读。
LaunchAgent 拉起 daemon 时,在 EnvironmentVariables 中显式写入 NODE_BINARY、NODE_EXTRA_CA_CERTS,避免「登录 shell 有 Node、守护进程没有」的经典坑。
将上述 curl 配进 cron 或 LaunchAgent,连续失败时 launchctl kickstart 重启服务,细节可与健康守护 HowTo对齐。
| 检查项 | 推荐 | 避免 |
|---|---|---|
| 管理面暴露 | 仅回环 + 隧道/反代单路径 | Dashboard 无鉴权对公网 |
| 令牌存储 | 0600 配置文件 + 专用系统用户 | 写进镜像层或 Git |
| 入站校验 | 静态路径 token + 可选 HMAC | 仅靠 IP 信任 |
步骤二:工作目录沙箱(每构建隔离)
OpenClaw handler 在验签通过后,用 CI 载荷里的 repository、ref、build_id 拼出唯一工作目录,例如 /var/tmp/oc-bundler/<build_id>,再执行浅克隆:
随后为 Bundler 指定沙箱内路径,避免多 Job 共用默认 vendor/bundle 造成锁竞争或缓存污染:
若需对比 lock 漂移,可在每次成功后 cp Gemfile.lock "$WORK_DIR/../last-good.lock",下一构建与当前文件做 diff -u 截取摘要行。
步骤三:脚本模板——触发 bundle check / outdated 与 diff 摘要
预检目标是在不写生产数据的前提下尽早暴露「lock 与解析不一致」「可升级 gem 潮」等问题。bundle check 验证当前 Gemfile.lock 是否可被满足;bundle outdated 列出落后于解析集的 gem,用 --parseable 便于脚本截断。
- ①
bundle check— 失败则预检短路并记录退出码。 - ②
bundle outdated --parseable | head -n 40— 写入摘要字段outdated_preview。 - ③ 可选:
diff -u ../last-good.lock Gemfile.lock | head -n 25— 作为lock_diff_preview。
跨境与 Git 源 gem 的环境变量(BUNDLE_RETRY、镜像、BUNDLE_GITHUB__COM 等)请直接对照Bundler 决策矩阵,本文不重复展开。
步骤四:失败重试与日志归档
弱网或 rubygems 限流时,bundle check 可能偶发失败。建议用壳层最多三次、间隔 1 / 2 / 4 秒 的退避包裹(与OpenClaw 失败恢复文一致),且仅在退出码非零且输出含超时/连接类关键字时重试,避免掩盖真正的 Gemfile 错误。
日志目录可轮换:按日期打包 gzip 或交给 logrotate;保留最近一次成功构建的 stdout 尾部便于与 Webhook 摘要对照。
步骤五:对接通用 HTTP Webhook 回传摘要
告警端点可能是自建 /hooks/ci、协作平台的 Incoming Webhook,或内部事件总线。约定最小 JSON 字段:status(ok|warn|fail)、summary(纯文本,≤2KB)、build_id、repo。需要鉴权时加 Authorization: Bearer <token>;若接收方要求 HMAC,可对原始 body 做 SHA256 写入 X-Hub-Signature-256 或自定义头,反代勿改写 JSON。
出站失败(超时、429、5xx)沿用 1/2/4 秒重试;以 repo+build_id 做幂等键,防止 CI 重投导致重复告警。嵌入样式可参考Discord 摘要步骤与CircleCI lockfile 回传中的字段映射思路。
排错 FAQ
CI 投递 502,OpenClaw 无日志?
先查隧道/反代是否指向错误端口;再用 curl -v 从本机模拟 POST,确认路径 token 与 handler 注册一致。
bundle check 在守护进程里报 Ruby 版本不符?
对齐 .ruby-version 与 LaunchAgent 的 PATH;必要时在脚本内 eval "$(rbenv init -)" 前确认非交互 shell 可用。
摘要太长导致 Webhook 413?
在 jq 组装前用 cut -c-1800 截断 summary,附件级细节留在本地日志文件路径字段中供 SSH 查阅。