OpenWork Den API 生产部署事故响应手册:Render 部署、健康检查与回滚实战
【免费下载链接】openworkThe open-source alternative to Claude Cowork (powered by opencode)项目地址: https://gitcode.com/GitHub_Trending/ope/openwork
本文是 OpenWork 仓库中 docs/den-api-deployment-incident-runbook.md 的完整展开版。该 runbook 面向 OpenWork 平台 on-call(值班)人员,规范了生产环境 Den API(运行于 Render 平台)的部署预防、告警契约与事故响应流程。读完本文,你将掌握 Den API 的 canonical 生产构建契约、Render 告警与升级策略、/health与/ready探针的源码级语义,以及一套可立即执行的五步事故响应流程。
服务背景:生产 Den API 是什么
runbook 中提到的服务是production Den API on Render,其源码位于 ee/apps/den-api(包名@openwork-ee/den-api)。这是 OpenWork EE 中的核心 API 服务,承载认证、组织、云能力、自动化、MCP 连接等大量路由(见 ee/apps/den-api/src/app.ts 中registerAuthRoutes、registerCloudRoutes、registerAutomationRoutes等一系列注册调用)。
runbook 的拥有者(Owner)是OpenWork platform on-call,这意味着本文所有内容都以「值班工程师在生产事故中能快速照做」为设计目标:构建契约、告警内容、响应步骤都追求最小化决策成本。
预防与晋升:canonical 原生生产契约
runbook 强调,原生(native,即非容器镜像)生产部署的唯一正确契约是以下三条命令:
pnpm install --frozen-lockfile --trust-lockfile pnpm --filter @openwork-ee/den-api run build pnpm --filter @openwork-ee/den-api start构建阶段发生了什么
pnpm --filter @openwork-ee/den-api run build实际执行 ee/apps/den-api/scripts/build.mjs(见 ee/apps/den-api/package.json 中的"build": "node ./scripts/build.mjs")。该脚本依次完成:
- 解析 workspace 依赖图并逐个构建:通过
pnpm run build:workspace-dependencies(即pnpm --filter '@openwork-ee/den-api^...' --if-present run build)构建 Den API 依赖的所有 workspace 包——包括@openwork/types、@openwork/automations、@openwork/email、@openwork/enterprise-mcp-client、@openwork-ee/den-db、@openwork-ee/cloud-runtime、@openwork-ee/telemetry等(依赖清单见 ee/apps/den-api/package.json)。 - 校验生产导出目标文件存在:
verifyProductionWorkspaceExports()递归遍历 workspace 依赖,检查每个依赖package.json中exports字段解析出的生产目标(node/import/default条件)是否真实存在;缺失即抛出Workspace production exports are missing并终止构建。这正是 runbook 中「rejects production exports whose target file is absent」的代码级依据。 - TypeScript 编译:
tsc -p tsconfig.json产出dist/main.js(start脚本即node dist/main.js)。 - 可选 Sentry sourcemap 上传:当
DEN_UPLOAD_SENTRY_SOURCEMAPS=1时,要求SENTRY_AUTH_TOKEN、SENTRY_ORG、SENTRY_PROJECT、SENTRY_RELEASE齐备,先sentry-cli sourcemaps inject再upload。
此外,构建脚本会读取 apps/desktop/package.json 的版本号生成src/generated/app-version.ts;在未携带 desktop 源码的构建上下文(如 Docker 镜像)中,回退到0.0.0并可通过DEN_API_LATEST_APP_VERSION覆盖。
容器镜像走同一条构建路径
packaging/docker/Dockerfile.den 是 Den API 的官方 Dockerfile:它以多阶段方式pnpm install --frozen-lockfile --trust-lockfile(与原生契约第一条完全一致),随后仅拷贝 Den API 及其 workspace 依赖的源码,最后执行与原生构建相同的pnpm --dir /app/ee/apps/den-api run build。镜像默认暴露PORT=8788,并在CMD中直接node /app/ee/apps/den-api/dist/main.js启动——与 runbook 的原生start命令指向同一产物dist/main.js。
CI 冷启动校验
runbook 指出,CI 还会在不带 development 条件的情况下冷启动dist/main.js(对应den-api-production-package生产包校验,命令为pnpm evals:pr specs/den-api-production-package.test.ts)。这条校验的意义在于:生产启动路径必须只依赖发布包中的文件,任何仅存在于开发条件(--conditions=development)下的依赖泄露都会在 CI 中被拦截。
晋升(Promotion)门槛
无论走哪种路径,晋升都必须同时满足两个条件:
- 生产包 spec(production-package 校验)通过;
Publish EE Artifacts / Build openwork-den-api镜像 smoke check 通过。
Render 侧必须使用上面三条命令,或直接部署 CI 验证过的ghcr.io/different-ai/openwork-den-api镜像,禁止使用偏离 canonical 契约的临时构建。
告警契约(Alert contract)
需要配置的 Render 部署通知事件
在 Render 上为 Den API 服务配置部署通知,必须覆盖以下六类事件:
| 事件 | 含义 |
|---|---|
| build failure | 构建阶段失败 |
| pre-deploy failure | 预部署(pre-deploy 命令/检查)失败 |
| startup failure | 启动失败(进程未能进入监听状态) |
| unhealthy service | 服务健康检查持续不通过 |
| canceled deploy | 部署被取消 |
| rollback | 发生自动/手动回滚 |
所有生产事件必须路由到platform incident channel与on-call 集成。
告警时效与升级策略
- 第一个失败阶段出现后5 分钟内必须告警;
- 同一 Render deploy ID 的后续更新应去重(避免刷屏);
- 出现以下任一情况必须升级:
/ready持续不健康超过10 分钟;- 发生自动回滚。
每条告警必须包含的字段
runbook 明确列出告警内容的最小字段集,缺一不可:
- 服务名与环境(service and environment)
- commit SHA 与部署 URL(deployment URL)
- Render deploy ID 与失败阶段(failing phase)
- 错误摘录(error excerpt)
- 负责人:OpenWork platform on-call
- 本 runbook 的 URL
- Render 回滚与重新部署链接
季度演练(Quarterly drill)
告警目标地址、on-call 排班与密钥有意不放在本公开仓库中。为验证链路可用,runbook 要求每季度执行一次安全的合成部署演练:
- 部署一个「启动命令故意无效」的合成版本;
- 确认告警接收时间< 5 分钟;
- 随后取消或回滚该部署;
- 在事故系统中记录演练结果,但不得提交目标地址 URL 或凭据。
事故响应(Response):五步流程
runbook 给出的响应流程可归纳为五个可执行步骤:
步骤 1:定位失败阶段
打开 Render 部署页面,判断失败发生在build / pre-deploy / startup / health哪个阶段。阶段不同,根因排查方向完全不同:build 失败通常指向依赖解析或导出缺失;startup 失败指向运行时配置或入口产物问题;health 失败指向进程已起但探针不通过。
步骤 2:ERR_MODULE_NOT_FOUND的处理
若错误为ERR_MODULE_NOT_FOUND(Node ESM 无法解析模块),在失败的 SHA 上执行:
pnpm evals:pr specs/den-api-production-package.test.ts该命令复现生产包冷启动校验。任何与 canonical 契约不一致的原生构建都不得晋升——不要通过临时拼凑包列表绕过校验。
步骤 3:区分/health与/ready
runbook 的核心判断原则:/health看进程存活,/ready看数据库就绪。源码完全印证了这一语义(见 ee/apps/den-api/src/app.ts):
GET /health:公开路由,直接返回{ ok: true, service: "den-api", version: env.serviceVersion }——只要进程能响应 HTTP 即通过;GET /ready:公开路由,执行db.execute(sqlselect 1)探测数据库连通性——成功返回{ ok: true, checks: { database: "ok" } },失败记录错误日志并返回503{ ok: false, checks: { database: "error" } }。
因此:进程存活但/ready持续失败,通常意味着数据库或迁移事故,而不是产物(artifact)问题。此时应把排查重心从部署切换到数据库连接、迁移脚本与DATABASE_URL配置上。旁证:仓库中与 Render 相关的就绪超时配置存在于 ee/apps/den-api/src/env.ts(RENDER_HEALTHCHECK_TIMEOUT_MS默认180000、RENDER_CUSTOM_DOMAIN_READY_TIMEOUT_MS默认240000),可结合值班环境实际值判断等待窗口。
步骤 4:回滚决策
当生产影响持续时,回滚到最近一次健康的部署是首选动作。runbook 同时给出两条红线:
- 不要在同一个未经验证的 SHA 上重建,不要用临时拼凑的包列表(ad hoc package list)修复;
- 回滚后若需修复,应走正常的代码修复 → canonical 构建 → CI 校验 → 晋升流程。
步骤 5:复盘归档
恢复后,将以下证据全部附加到事故记录(incident)中:
- 失败的部署(failed deploy)
- commit
- 告警送达时间戳(alert-delivery timestamp)
- 回滚记录
- 纠正性测试证据(corrective test evidence)
与仓库其他材料的关联
- 构建与镜像路径:ee/apps/den-api/scripts/build.mjs、packaging/docker/Dockerfile.den
- 启动命令与依赖清单:ee/apps/den-api/package.json
- 健康/就绪探针实现:ee/apps/den-api/src/app.ts
- 环境变量定义:ee/apps/den-api/src/env.ts 与 ee/apps/den-api/.env.example
- 本地启动指引:ee/apps/den-api/start.md
小结
这份 runbook 的价值在于把「生产 Den API 部署事故」的处置收敛为可重复执行的契约:构建只认 canonical 三命令或 CI 验证镜像,告警 5 分钟内必达并按需升级,响应五步走、先分阶段再分探针、必要时果断回滚并拒绝临时重建。值班工程师按本文执行,即可在最短时间内稳定生产、留下完整证据链。
【免费下载链接】openworkThe open-source alternative to Claude Cowork (powered by opencode)项目地址: https://gitcode.com/GitHub_Trending/ope/openwork
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考