Staging 端到端冒烟测试
这份手册用在一套可以随时丢弃的 staging 部署上,验证从网关登录一直到生成真实 pull request 的完整链路。涉及的范围是:一个 Cloud Agent 控制平面、一台 runner 主机,以及一个可以随时丢弃的 GitHub 仓库。
如果你只想在本地检查一下产品,不想用服务商的密钥,先用完整的本地 Docker 环境:
./deploy/local/dev.sh up
./deploy/local/dev.sh smoke
本地环境会实际跑一遍浏览器登录、控制平面和主机之间的对接、五个固定版本的 CLI,以及保留的原生会话;外部服务都换成了结果固定的模拟服务。真实服务商的行为和 GitHub 发布它测不到,这两处边界由这份 staging 手册单独检查。
这份清单在 2026-08 仓库拆分期间跑过的几次结果,保存为一份带日期的记录。它们并不能说明现在的任何一套部署能通过检查。
跑通一次能证明什么
完整跑通一次,能证明在所记录的版本和环境下,这些环节都是通的:身份登录、明确授予的 Agent 访问权限、主机注册、推理授权、沙箱执行和 GitHub 发布。光是任务成功,并不能证明发布没问题:发布要由所有者主动发起,之后发布器再异步处理一份不可变的工作区快照。
这次运行不涵盖迁移过来的归属关系和数据、并发、主机丢失,也没有覆盖每一道隔离边界。这些要分别按 cutover、部署可靠性和原生会话的上下文记忆去检查。网关契约归网关负责;开始之前,先确认网关上已经部署了相应的路由。
0. 开始之前
用一套可以随时丢弃的 staging 部署,要有 Docker/Compose、一份本地仓库,内存要够所选的 CLI 用。本地跑五个 CLI 的冒烟测试建议至少 8 GiB;对公众开放的多租户 staging 需要一台支持 Kata 的主机。
记下确切的发布 SHA 和网关环境。API、主机、sandbox manager 和沙箱都必须通过共用的部署和版本检查。
确认 staging 网关上的
GET /v1/identity/jwks能正常返回:```bash curl -sS -o /dev/null -w '%{http_code} %{url_effective}\n' \ "$GATEWAY_BASE_URL/v1/identity/jwks" ```用配置好的 dispatch 凭据,检查
/internal/model-catalog?user_id=<test-user>和/internal/users/<test-user>/agent-access。测试账号必须拿到agent.use,模型目录里也必须有你选的模型。只要缺少访问端点,或者 dispatch 凭据被拒绝,这次就跑不下去。已经退役的/internal/mcp-registry不是必需的;/internal/users/<id>/status只用来给 Profile 页面提供邮箱。准备一个能在浏览器里完成网关登录的账号,以及注册主机所需的基础设施管理权限。
选一个可以随时丢弃的 GitHub 仓库,通过部署支持的 GitHub App 或发布凭据,给它配置写入和创建 PR 的权限。记下它的 base 分支。不要用别人在用的仓库。
1. 配置
控制平面和主机各用一份独立的私有环境文件。分别从 control-plane/.env.example 和 host/.env.example 改起,参考资料是 ENVIRONMENT.md。Agent 数据库和网关数据库要分开。
部署自己用的 secret 只生成一次,并且不要放进版本控制:
for name in AGENT_SESSION_SECRET AGENT_CONTROL_TOKEN_SECRET AGENT_SOURCE_CONTROL_ENCRYPTION_KEY; do
printf '%s=%s\n' "$name" "$(openssl rand -hex 32)"
done
加密密钥不要变,不然已保存的连接就解不开了。GATEWAY_GRANT_DISPATCH_TOKEN 是两边共用的服务凭据:Agent 和网关两侧必须一致,staging 和 production 之间必须不同。Agent 拿不到网关的签名密钥,也拿不到网关账号数据库的凭据。
设置确切的
GATEWAY_ISSUER、JWKS 和 authorize 地址、回调白名单、Web 的源和 base path,以及浏览器访问的 API 路径。如果有已有数据,先准备好身份绑定。明确设置:Compose 项目名、沙箱镜像、要注册的主机名、sandbox manager 凭据和反向路由、三条隧道各自的目标地址和密钥,以及主机上互不重叠的出口地址池和 DNS 解析器。
用当前生效的环境文件,在私密的地方渲染出最终配置。如果直接对控制平面执行 Compose 命令,要导出
AGENT_DEPLOYMENT_SHA;部署脚本会自己设置它。渲染出来的配置里有 secret,不要贴进验收日志。
2. 启动控制平面
按部署可靠性里的部署流程操作。如果是从零开始的源码部署,它的 prepare 和 prepare-database 两个阶段会构建镜像、启动 Postgres、执行迁移并检查身份命名空间,再启动主机就绪检查要用到的 API 和 MCP 监听器。等主机在第 4 节报告就绪之后,再完成激活。整个过程中,部署的项目名和配置根目录都不要变。
迁移在本地仓库当前的 head 上成功退出。API 启动时不会自动创建缺失的表。
主 API 的
/healthz能响应,默认端口 8000。MCP 专用监听器的
/healthz能响应,默认端口 8001;MCP 隧道指向的就是这个监听器。reaper 和发布 worker 都在运行。整体健康检查通过,并不代表授权续期和发布一定正常。
3. 登录:走一遍完整的身份流程
打开 Web 应用,开始登录。浏览器会跳到网关的授权页面,再经由 Agent 的回调回来,建立会话。
GET /v1/session/me返回测试用户的id和agent_access: {allowed, permissions},不包含账号角色和个人资料字段。创建任务之前,确认明确拿到了agent.use。确认 Agent 会话是用它自己的 secret 签名的,并带有配置的签发方。Agent 的存储里不保留任何网关的会话令牌。运行日志里不要记录 cookie 或令牌内容。
4. 注册主机
用基础设施管理员权限,带上选好的
host名,调用POST /admin/agent/runner-hosts/enroll-token。响应里会给出一个只能用一次的注册令牌,把它放进主机的私有配置。用
deploy/host/deploy.sh把主机部署到同一个目标版本。主机进程会准备并证明沙箱镜像、启动隧道和 sandbox manager、探测两个中继,最后写入"本代已完成"的标记。直接启动 runner 的 Compose 容器,过不了这一关。GET /admin/agent/runner-hosts显示:刚收到的在线心跳、预期的部署能力,以及可以访问的 sandbox manager URL。再从控制平面检查一下反向 sandbox manager 路由。完成控制平面的激活,确认它的就绪检查对预期的主机和 API SHA 通过。
如果要测试注册被拒的情况,另外拿一个用完即弃的令牌:用不同的主机名去兑换,必须失败,而且令牌不能被消耗掉。把这次拒绝记下来;不要试图重新注册一台无关的线上主机。
5. 跑通一个完整的任务
在 Integrations 里连接并授权这个临时仓库。
在预定的 base 分支上创建一个任务,改动要小、容易验证,比如新建一个
CONTRIBUTING.md,里面写一句指定的话。看到状态先是
queued,然后被某台主机认领。记下任务、attempt 和主机的标识,以及不涉密的授权 ID。确认沙箱拿到的推理授权,限定在这个账号所选的模型上。确认事件能实时推送到浏览器,并且至少有一次模型或工具调用成功。
确认这一轮成功了,文件改动符合预期。你不发起,就什么都不会发布:在对话里点 Create PR,等发布完成,再打开那个真实的 draft pull request。检查目标分支、作者和 diff,记下它的 URL。光是执行成功是不够的。
在应用里列出保留工作区的文件,并打开一个终端。
6. 那些过一阵才会出问题的地方
故障注入只能在可以随时丢弃的 staging 部署上做,每做完一项,都要把设置改回原样。
续期:让一个轮次一直跑,跨过好几次续期。初始授权的 TTL 是 120 秒(每 30 秒一次,共四次);网关每续期一次延长 300 秒。确认续期真的发生了,模型调用也一直在继续。一个很快就跑完的轮次,根本碰不到这条边界。
取消和撤销:另起一个正在运行的轮次,然后取消它。确认 worker 收到并确认了取消、任务进入了取消的终态、被放弃的成员凭据已经不能再用,并且有授权被撤销的证据。撤销只是让授权提前过期;如果撤销的 HTTP 调用失败了,还有 TTL 兜底。
出错时一律拒绝:让网关不可用,然后尝试全新登录,并发起一个新的受保护所有者请求或创建任务,两者都不能放行。已有会话的
/me必须显示暂时性失败,且不能露出受保护的内容。恢复网关的连通性后,确认一切恢复正常。控制平面中断:在任务运行时,停掉这套可丢弃部署的 API。网关并不掌管这个 attempt,也不会去结束它;续期会停止,授权随之过期。恢复 API 之后,在这里检查租约和 reaper 的处理是否正确。
按上下文记忆里的方法,分别检查运行中发送后续消息,以及同一个容器在空闲后的恢复。
7. 收尾清理
用记下的项目名,停掉这些可丢弃的环境。验收证据收集完之前,数据先留着。删除卷是不可恢复的;只有数据库确实可以丢弃的环境,才用
down -v。部署退役时,删掉临时分支或临时仓库,并撤销只用于测试的仓库凭据和 dispatch 凭据。
把 staging 上所有故障注入的设置都改回去,并按记录一节的要求记下结果。
记录
边跑边记:每个编号小节的日期和时间(UTC)、结果和备注,以及源 SHA、环境、主机、任务和 PR 的标识。这份记录和部署自己的验收证据放在一起保存。