13 KiB
Code Queue Deploy
bun scripts/cli.ts codex deploy <commitId> 是旧兼容入口,现已禁用。原因是它会通过 backend-core host.ssh 维护通道直连 D601 部署 Code Queue,把维护入口扩张成第二套部署系统。
Code Queue 后续正式生产部署必须走一条受控 CD 路径并单独审查;当前阶段只提供 dev artifact consumer。deploy apply --env dev --service code-queue 或 artifact-registry deploy-service --env dev --service code-queue 可以消费 D601 registry 中的 unidesk/code-queue:<commit>,只更新 unidesk-dev Code Queue execution slice,并通过 Kubernetes API service proxy 验证健康。--env prod --service code-queue 必须明确 unsupported,不能执行生产 artifact deploy、rollout 或 manifest 变更。persistent dev apply 的完整服务范围见 docs/reference/dev-environment.md,Code Queue temporary smoke 仍通过 ci run-dev-e2e,规则见 docs/reference/dev-ci-runner.md。
Command
bun scripts/cli.ts codex deploy <commitId>
该命令必须返回结构化错误,说明维护通道直连 D601 部署已禁用;不得再创建后台部署 job。--skip-build 不再支持。
Pipeline
历史部署 job 曾固定为以下步骤;它们现在只能作为未来受控 Code Queue CD 的目标行为,不能由 codex deploy 或维护通道直连触发:
- 对 Code Queue 部署先确保 PostgreSQL 中存在
unidesk_deploy_ssh_identities(id='github.com'),该记录保存 GitHub deploy SSH identity 的 private key、public key fingerprint 和 github.comknown_hosts行。未来受控 CD 不得把 secret 写入 task payload、deploy 日志、Docker image 或 Kubernetes Secret。 - 在 D601 的 deploy cache 中通过本机 provider-gateway WS egress proxy 执行
git fetchremote,并用git archive <commitId>导出 tracked files 到一次性 export 目录;不得让 D601 直连 GitHub,也不得临时创建 SSH SOCKS、公网 master proxy 或 backend-core/provider-ingress fallback。 - 用
rsync --delete同步导出的 repo 到/home/ubuntu/cq-deploy,保留.state/、logs/、.git/、node_modules/和dist/。同步完成后、任何 scheduler/read/write rollout 前,必须运行 Code Queue hostPath source guard:bun scripts/code-queue-source-guard.ts --root /home/ubuntu/cq-deploy或等价bun scripts/cli.ts deploy guard code-queue-source --root /home/ubuntu/cq-deploy。该 guard 至少扫描src/components/microservices/code-queue/src/**/*.ts的相对import/export ... from/import(...),确认目标文件存在;失败必须返回结构化degradedReason=missing-relative-import-target或source-root-missing,并阻止 rollout。 - 在 D601 用目标 Docker daemon 的本地 BuildKit builder 构建
unidesk-code-queue:d601,复用 D601 上已有基础镜像、inline cache 和 Code Queue build-base;provider-gateway WS egress 是唯一允许的构建代理通道,只作为本次 build 的环境变量与 build-arg 注入,并配合本次 build 的--network host让 RUN 阶段访问 D601 宿主 loopback proxy,不能污染 D601 宿主 Docker/HTTP proxy 配置,不能新建 SSH SOCKS、公网 master proxy 或直连 fallback。 docker save镜像并导入原生 k3s containerd:docker save unidesk-code-queue:d601 | sudo ctr --address /run/k3s/containerd/containerd.sock -n k8s.io images import -。导入后必须用同一个 containerd socket 验证unidesk-code-queue:d601tag 存在;D601 Docker daemon 的本地 tag 不是 k3s containerd 的 source of truth。kubectl apply -f src/components/microservices/k3sctl-adapter/k3s/code-queue.k8s.yaml,其中包含 Code Queue、d601-provider-egress-proxy和d601-tcp-egress-gateway。apply 后必须验证code-queue、code-queue-read、code-queue-write、d601-provider-egress-proxy、d601-tcp-egress-gateway这些 Deployment 的 container image 都是unidesk-code-queue:d601,不能让 kubelet 回退到 Docker Hub 或其他外部 registry。- 将解析后的 40 位 remote commit 写入
deployment/code-queue的CODE_QUEUE_DEPLOY_COMMIT/CODE_QUEUE_DEPLOY_REQUESTED_COMMIT,并记录到 Deployment annotation。 kubectl -n unidesk rollout restart deployment/d601-tcp-egress-gateway deployment/code-queue并等待 rollout 完成。- 通过 backend-core 的真实微服务代理读取 Code Queue
/health,强制校验deploy.commit等于本次解析出的 remote commit;如果健康的是旧服务或旧 Pod,job 必须失败。
HostPath Source Guard
生产 unidesk namespace 的 Code Queue scheduler/read/write 仍处在 hostPath source 过渡模式:Pod 内 /app 和 /root/unidesk 都挂载 D601 host 的 /home/ubuntu/cq-deploy。这意味着镜像内已经包含的源码会被 hostPath 覆盖,镜像构建成功不能证明运行时源码完整。已知失效模式是 hostPath repo 部分同步:src/components/microservices/code-queue/src/index.ts 已包含 ./runtime-preflight 导入,但 /home/ubuntu/cq-deploy/src/components/microservices/code-queue/src/runtime-preflight.ts 缺失,scheduler 启动即因 Bun 模块解析失败进入 CrashLoopBackOff。
/home/ubuntu/cq-deploy 是生产 Code Queue/k3s 共享 hostPath 部署仓库,也是当前 code-queue.k8s.yaml 中 repo、state 和 logs hostPath 的根。/home/ubuntu/unidesk-code-queue-deploy 是历史/开发工作区口径,不是生产 Pod 的 /app source mount;生产 rollout 判断必须以 /home/ubuntu/cq-deploy 为准。若两者需要保留软链接或迁移关系,必须先在 manifest、config 和文档中显式统一,不能让部署脚本从一个路径同步而 Pod 从另一个路径启动。
人工排查 D601 生产 k3s 状态时必须显式使用原生 k3s kubeconfig:
KUBECONFIG=/etc/rancher/k3s/k3s.yaml kubectl -n unidesk get deploy,svc,pod,endpoints
D601 默认 kubectl context 可能指向 Docker Desktop、kind 或其他本地集群,不能作为 UniDesk 原生 k3s scheduler 是否 ready、Service 是否有 endpoint、Pod 是否 CrashLoop 的证据。
hostPath source 模式只允许作为过渡态。长期生产 Code Queue 应收敛到 commit-pinned artifact/image CD:以 pushed commit 为版本真相,CI 产出带 source commit label 的镜像,CD 只消费 commit-pinned image、更新 manifest/env/annotation 并验证 live health commit;生产 Pod 不应再用可部分同步的 hostPath source 覆盖镜像内应用源码。
Observability
未来受控 Code Queue CD 实现后,部署触发本身不应阻塞等待完成。返回 JSON 中必须包含 run id、status command 或等价查询入口;后台日志必须有界可查,失败时能显示最后日志尾部。
部署 run 到 succeeded 时,必须已经完成 live commit 验证。需要人工复核时可用以下命令确认 deploy.commit:
bun scripts/cli.ts microservice health code-queue
bun scripts/cli.ts microservice proxy code-queue '/api/tasks/overview?limit=5&transcriptLimit=1&compact=1&afterSeq=0&preferId='
D601 原生 k3s 的人工诊断必须显式使用 host kubeconfig:KUBECONFIG=/etc/rancher/k3s/k3s.yaml kubectl -n unidesk ...。D601 上的默认 kubectl context 可能指向 Docker Desktop 或其他本地集群,不能作为 UniDesk Code Queue 部署是否 ready 的证据。部署后直接查 k3s 时,至少确认 deployment/code-queue、code-queue-read、code-queue-write、d601-provider-egress-proxy 和 d601-tcp-egress-gateway ready,两个 egress Service 的 Endpoints 非空,Pod 环境中的 UNIDESK_DEPLOY_REQUESTED_COMMIT/CODE_QUEUE_DEPLOY_REQUESTED_COMMIT 等于期望 commit,并且 scheduler /health 暴露 PostgreSQL ready、storage.lastError=null、egress proxy connected、stale active/retry_wait reconcile 状态和 MiniMax NO_PROXY 例外。
bun scripts/cli.ts microservice diagnostics code-queue 必须作为 Code Queue 的长期诊断入口。它必须显式报告 d601-provider-egress-proxy 和 d601-tcp-egress-gateway 的 Deployment available、Endpoint non-empty、scheduler 到 PostgreSQL route、以及 stale active/retry_wait reconcile;任何一项失败都应让诊断结果 degraded/failing,而不是只显示 scheduler HTTP healthy。
Pull Request Delivery
Code Queue worker 可以在任务明确要求审查型交付时创建 Pull Request。PR 交付不是默认出口;默认集成仍遵循项目当前 master-only 规则,直到具体任务或指挥官要求改为 PR。PR 型任务必须从最新目标线创建短生命周期分支,报告源分支、目标分支、PR URL、关联 issue、验证证据和未完成风险;分支命名应使用 probe/、code-queue/ 或其他明确任务前缀,禁止把隐藏分支当成长期交付状态。
Code Queue runtime 提供 /api/runtime-preflight 作为 PR 能力探测入口;CLI 稳定入口是 bun scripts/cli.ts codex pr-preflight [--remote] [--push-dry-run --push-dry-run-ref refs/heads/probe/<name>] [--issue N]。默认请求只检查本地工具、凭证可见性、Git worktree、HOME、known_hosts、agent port 和 proxy DNS;--remote 会增加 GitHub 网络、issue API、SSH/HTTPS git ls-remote、GitHub SSH、gh auth status、gh repo view、gh issue view 和只读 gh pr list 探测;--push-dry-run 会额外执行 git push --dry-run,验证远端写权限但不创建分支。探测输出只报告 GH_TOKEN/GITHUB_TOKEN 是否存在,不得输出 token 内容。backend-core 的稳定 code-queue proxy 必须把 /api/runtime-preflight 路由到 D601 scheduler,而不是主 server code-queue-mgr,因为 token 和 PR runner 能力属于执行面环境。
PR 创建依赖以下最小运行时能力:
- runtime image 必须包含
git、gh、jq、ca-certificates、curl和openssh-client;D601 provider dev container 准备脚本也必须补齐这些工具。 - GitHub 凭证只能通过运行时 secret、环境变量或已有 SSH identity 注入。优先使用
GH_TOKEN,兼容GITHUB_TOKEN;不得把 token 写入 Git remote、任务 prompt、日志、镜像或仓库文件。 CODE_QUEUE_REMOTE_CODEX_ENV_KEYS默认允许把GH_TOKEN/GITHUB_TOKEN以及GH_HOST、GITHUB_API_URL、GH_REPO从 scheduler 传给 provider dev container,供隔离执行环境内的gh repo view、gh issue view、gh pr list和gh pr create使用。- DEV 的持久注入路径复用
unidesk-dev-runtime-secrets:把GH_TOKEN或GITHUB_TOKEN写入该 Secret 后,通过受控deploy apply --env dev --service code-queue或等价 dev-only rollout 重启 Code Queue scheduler/read/write。default/prod runner 使用生产unidesknamespace 的code-queue-envSecret;仅修复 dev Secret 不会覆盖 default queue scheduler。不要在 PROD Code Queue 上直接 patch Secret 或 rollout,生产 token 覆盖需要显式 release/runtime 授权。
安全验证顺序固定为先只读、再 dry-run、最后才创建真实 PR。优先执行 /api/runtime-preflight、/api/runtime-preflight?remote=1 和带 pushDryRun=1 的 probe ref;只有工具、token、网络和 push dry-run 都满足且任务明确允许时,才创建 draft PR 或普通 PR。若创建真实 probe PR,最终报告必须记录 URL 并说明保留或关闭状态。
preflight failure 必须定位到具体缺失项。已知必须区分的状态包括:gh/hub 缺失、GH_TOKEN/GITHUB_TOKEN/GH_HOST/GITHUB_API_URL/GH_REPO 未注入、/root/.config/gh/hosts.yml 与 /root/.git-credentials 缺失、SSH Git 可读但 GitHub issue/API 匿名访问返回 404、匿名 HTTPS Git 不可用、以及 HTTP_PROXY/HTTPS_PROXY 指向的 egress proxy 在 runner 内不可解析。发现这类缺口时,worker 应报告 preflight error 和阻塞项,不得强行创建 PR。
Boundaries
Code Queue 由 D601 k3s/k8s 控制面代管,不再通过 server rebuild、codex deploy、维护通道直连 D601 或手工 docker compose up 作为正式部署路径。Code Queue 部署必须在自身正在执行任务时仍可运行;服务重启后由 restart-recovery 恢复任务状态,不能等待当前 Code Queue task 退出后再部署。
TCP Egress Gateway
D601 k3s Pod 不能依赖主 server 公开 15432/4255 作为直连 TCP 入口;PostgreSQL 也不会自动使用 HTTP proxy 环境变量。code-queue.k8s.yaml 因此提供一个通用 d601-tcp-egress-gateway:
- Pod 内业务只访问集群内 Service:
d601-tcp-egress-gateway.unidesk.svc.cluster.local:15432和:4255。 - gateway 通过 D601 provider-gateway egress proxy 的 HTTP CONNECT 转发到底层 TCP 目标。
- 新增 TCP 依赖时只扩展
TCP_EGRESS_ROUTES,不要在业务容器里散落公网直连地址或 ad hoc 隧道脚本。