Files
pikasTech-unidesk/docs/reference/codex-deploy.md
T

15 KiB
Raw Blame History

Code Queue Deploy

bun scripts/cli.ts codex deploy <commitId> 是旧兼容入口,现已禁用。原因是它会通过 backend-core host.ssh 维护通道直连 D601 部署 Code Queue,把维护入口扩张成第二套部署系统。

Code Queue 后续正式生产部署必须走一条受控 CD 路径并单独审查;当前阶段只提供 dev artifact consumer 的 dry-run/source/contract readiness。deploy apply --env dev --service code-queue --dry-runartifact-registry deploy-service --env dev --service code-queue --dry-run 可以计划消费 D601 registry 中的 unidesk/code-queue:<commit>,但输出必须显示 selfBootstrapGuardrequiresSupervisorApproval、pull-only/no-build、image tag/digest provenance,并说明只会在获授权后更新 unidesk-dev Code Queue execution slice。非 dry-run DEV apply 必须由 human operator/supervisor 在 Code Queue 任务之外授权;当前 Code Queue runner 不能自己上线 Code Queue。--env prod --service code-queue 必须明确 unsupported,不能执行生产 artifact deploy、rollout 或 manifest 变更。persistent dev apply 的完整服务范围见 docs/reference/dev-environment.mdCode Queue temporary smoke 仍通过 ci run-dev-e2e,规则见 docs/reference/dev-ci-runner.md

The reproducible dry-run delivery path is:

  1. CI publishes 127.0.0.1:5000/unidesk/code-queue:<full-sha> from pushed Git and reports the immutable digest/label summary.
  2. A runner or operator runs bun scripts/cli.ts deploy plan --env dev --service code-queue or bun scripts/cli.ts deploy apply --env dev --service code-queue --commit <full-sha> --dry-run; this is non-mutating evidence only.
  3. A human operator reviews the dry-run and, if accepted, separately authorizes DEV apply. That apply may touch only unidesk-dev Code Queue execution objects.
  4. PROD remains unsupported. A dry-run or plan may document the gap, but no Code Queue runner may perform prod apply, rollout restart, scheduler/runner rebuild, interrupt or cancel as part of delivering Code Queue itself.

This contract is checked by bun scripts/code-queue-cicd-dry-run-contract-test.ts. The test is intentionally lightweight and does not run full e2e, Playwright, Code Queue deployment, or task interruption flows.

Command

bun scripts/cli.ts codex deploy <commitId>

该命令必须返回结构化错误,说明维护通道直连 D601 部署已禁用;不得再创建后台部署 job。--skip-build 不再支持。

Pipeline

历史部署 job 曾固定为以下步骤;它们现在只能作为未来受控 Code Queue CD 的目标行为,不能由 codex deploy 或维护通道直连触发:

  1. 对 Code Queue 部署先确保 PostgreSQL 中存在 unidesk_deploy_ssh_identities(id='github.com'),该记录保存 GitHub deploy SSH identity 的 private key、public key fingerprint 和 github.com known_hosts 行。未来受控 CD 不得把 secret 写入 task payload、deploy 日志、Docker image 或 Kubernetes Secret。
  2. 在 D601 的 deploy cache 中通过本机 provider-gateway WS egress proxy 执行 git fetch remote,并用 git archive <commitId> 导出 tracked files 到一次性 export 目录;不得让 D601 直连 GitHub,也不得临时创建 SSH SOCKS、公网 master proxy 或 backend-core/provider-ingress fallback。
  3. rsync --delete 同步导出的 repo 到 /home/ubuntu/cq-deploy,保留 .state/logs/.git/node_modules/dist/。同步完成后、任何 scheduler/read/write rollout 前,必须运行 Code Queue hostPath source guardbun 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-targetsource-root-missing,并阻止 rollout。
  4. 在 D601 用目标 Docker daemon 的本地 BuildKit builder 构建 unidesk-code-queue:d601,复用 D601 上已有基础镜像、inline cache 和 Code Queue build-baseprovider-gateway WS egress 是唯一允许的构建代理通道,只作为本次 build 的环境变量与 build-arg 注入,并配合本次 build 的 --network host 让 RUN 阶段访问 D601 宿主 loopback proxy,不能污染 D601 宿主 Docker/HTTP proxy 配置,不能新建 SSH SOCKS、公网 master proxy 或直连 fallback。
  5. docker save 镜像并导入原生 k3s containerddocker save unidesk-code-queue:d601 | sudo ctr --address /run/k3s/containerd/containerd.sock -n k8s.io images import -。导入后必须用同一个 containerd socket 验证 unidesk-code-queue:d601 tag 存在;D601 Docker daemon 的本地 tag 不是 k3s containerd 的 source of truth。
  6. kubectl apply -f src/components/microservices/k3sctl-adapter/k3s/code-queue.k8s.yaml,其中包含 Code Queue、d601-provider-egress-proxyd601-tcp-egress-gateway。apply 后必须验证 code-queuecode-queue-readcode-queue-writed601-provider-egress-proxyd601-tcp-egress-gateway 这些 Deployment 的 container image 都是 unidesk-code-queue:d601,不能让 kubelet 回退到 Docker Hub 或其他外部 registry。
  7. 将解析后的 40 位 remote commit 写入 deployment/code-queueCODE_QUEUE_DEPLOY_COMMIT / CODE_QUEUE_DEPLOY_REQUESTED_COMMIT,并记录到 Deployment annotation。
  8. kubectl -n unidesk rollout restart deployment/d601-tcp-egress-gateway deployment/code-queue 并等待 rollout 完成。
  9. 通过 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 kubeconfigKUBECONFIG=/etc/rancher/k3s/k3s.yaml kubectl -n unidesk ...。D601 上的默认 kubectl context 可能指向 Docker Desktop 或其他本地集群,不能作为 UniDesk Code Queue 部署是否 ready 的证据。部署后直接查 k3s 时,至少确认 deployment/code-queuecode-queue-readcode-queue-writed601-provider-egress-proxyd601-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-proxyd601-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>] [--pr-create-dry-run --pr-create-dry-run-head <head>] [--issue N]。默认请求只检查本地工具、凭证可见性、Git worktree、HOME、known_hosts、agent port 和 proxy DNS--remote 会增加 GitHub 网络、issue API、SSH/HTTPS git ls-remote、GitHub SSH、gh auth statusgh repo viewgh issue read/view 和只读 gh pr list 探测;--push-dry-run 会额外执行 git push --dry-run,验证远端写权限但不创建分支;--pr-create-dry-run 会在 runner 内生成受控 PR body 并执行 scripts/cli.ts gh pr create --dry-run,只证明 PR body guard 和命令形态可用,不 POST GitHub。探测输出只报告 GH_TOKEN/GITHUB_TOKEN 是否存在,不得输出 token 内容,并通过 prCapabilityContract 明确 token source、target branch、expected PR handoff、dry-run 不写远端和 merge unsupported 边界。缺少 runner env token 时,authBroker.source="broker/auth-broker-needed" 是标准结构化证据;系统 gh binary 缺失必须与 UniDesk REST bun scripts/cli.ts gh 可用性分开报告。backend-core 的稳定 code-queue proxy 必须把 /api/runtime-preflight 路由到 D601 scheduler,而不是主 server code-queue-mgr,因为 token 和 PR runner 能力属于执行面环境。

PR 创建依赖以下最小运行时能力:

  • runtime image 必须包含 gitghjqca-certificatescurlopenssh-clientD601 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_HOSTGITHUB_API_URLGH_REPO 从 scheduler 传给 provider dev container,供隔离执行环境内的 gh repo viewgh issue read/viewgh pr listgh pr create 使用。
  • DEV 的持久注入路径复用 unidesk-dev-runtime-secrets:把 GH_TOKENGITHUB_TOKEN 写入该 Secret 后,通过受控 deploy apply --env dev --service code-queue 或等价 dev-only rollout 重启 Code Queue scheduler/read/write。default/prod runner 使用生产 unidesk namespace 的 code-queue-env Secret;仅修复 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,以及带 prCreateDryRun=1 的 PR body/create dry-run guard;只有工具、token、网络、push dry-run 和 PR body guard 都满足且任务明确允许时,才创建 draft PR 或普通 PR。若创建真实 probe PR,最终报告必须记录 URL 并说明保留或关闭状态。

preflight failure 必须定位到具体缺失项。已知必须区分的状态包括:auth-missingGH_TOKEN/GITHUB_TOKEN 未注入,且需要 env token 或 auth-broker)、control-plane-missing(远程 frontend/backend-core/code-queue proxy 不可达)、git-remote-gapgit ls-remotegit push --dry-run 失败)、系统 gh/hub 缺失、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 rebuildcodex 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 隧道脚本。