Files
pikasTech-HWLAB/docs/reference/spec-v02-cicd.md
T
2026-05-30 08:04:36 +08:00

296 lines
30 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# v0.2 CI/CD 规格
本文是 HWLAB `v0.2` 在 G14 上接入 CI/CD 的长期规格。目标是把 `v0.2` 作为独立加法 lane 接入现有 G14 k3s、Tekton、GitOps 和 Argo CD 体系,同时保持 `G14` DEV/PROD 发布面稳定。
实施跟踪见 [pikasTech/HWLAB#530](https://github.com/pikasTech/HWLAB/issues/530),env 容器复用、三变量启动和 git mirror 加速设计见 [pikasTech/HWLAB#572](https://github.com/pikasTech/HWLAB/issues/572)。原 `docs/plan/hwlab-v02-namespace-cicd.md` 阶段计划全文已迁入 #530 评论。本文只记录稳定规格、边界和判定标准;不要把一次性执行记录、排障流水账或临时证据写入本文。
## 在系统中的职责划分
`v0.2` CI/CD 是 G14 上的加法 lanesource branch、GitOps branch、runtime namespace、artifact catalog、Argo Application、Tekton Pipeline 和 FRP 入口均独立于 DEV/PROD。它共享 G14 k3s、Tekton controller、Argo CD controller、本地 registry 和构建工具,但不能复用 DEV/PROD runtime path、namespace、Application 或公网端口作为 v02 发布证据。code-only fast lane 必须消费独立 `devops-infra` 集群提供的 git mirror/relay;该 mirror/relay 是跨项目 DevOps 基础设施,不属于 `hwlab-v02` runtime namespace,也不改变当前 G14 registry 的部署位置或镜像引用真相。
## 内部架构
CI/CD 内部由 UniDesk 手动触发入口、PipelineRun、component planner、BuildKit publish、GitOps promotion、Argo sync、GitHub flush 和公网验收构成。`v0.2` 不设置 branch poller、control-plane reconciler 或其他 CronJobsource branch 只保存源码和人写配置;`v0.2-gitops` branch 保存 catalog 和 rendered runtime desired statelive runtime 是最终通过证据。
`v0.2` 的 GitOps 写路径采用真正写 mirrorpromotion 先把 `v0.2-gitops` 写入 `devops-infra` 本地 git mirror/relayArgo CD 从本地 mirror/relay 读取该 revision 并 rolloutCI 关键路径不等待 GitHub push。GitHub `pikasTech/HWLAB` 仍是长期源码与归档上游,但对 `v0.2-gitops` 来说是由 mirror/relay 负责 flush 的异步上游,不再是 promotion task 的同步写入目标。
## API 接口说明
| 接口 | 说明 |
| --- | --- |
| `scripts/g14-gitops-render.mjs --lane v02` | v02 GitOps render 入口,负责 namespace、runtime path、catalog 和 endpoint 固定。 |
| Tekton `hwlab-v02-ci-image-publish` | 构建 affected images、复用 unchanged digest,并 promotion 到 `v0.2-gitops`。 |
| `devops-infra` git mirror/relay | 读写 `v0.2` allowlist refsCI 读 source/catalog、写 `v0.2-gitops`,并通过手动 CLI flush 到 GitHub。 |
| Argo `argocd/hwlab-g14-v02` | 从 `devops-infra` 本地 mirror/relay 的 `v0.2-gitops:deploy/gitops/g14/runtime-v02` 同步到 `hwlab-v02`。 |
| `http://74.48.78.17:19666/` | v02 Cloud Web 公网入口。 |
| `http://74.48.78.17:19667/health/live` | v02 API/live 公网验收入口。 |
## 规格目标
- `v0.2` 固定作为 G14 上的新增 CI/CD lane,不改写现有 `G14` DEV/PROD lane。
- `v0.2` source branch 只保存源码、人写配置、模板、脚本和文档;CI/CD 生成物只进入 `v0.2-gitops`
- `hwlab-v02` 是唯一 runtime namespace`74.48.78.17:19666/19667` 是唯一公网验收入口。
- 共享 G14 k3s、Tekton controller、Argo CD controller、本地 registry、工具镜像和脚本库;隔离分支、catalog、runtime path、Application、Pipeline、ServiceAccount、SecretRef、PVC 和 FRP 入口。
- 旧 DEV/D601/main 门禁不得进入 `v0.2` 发布调用链;新增检查只覆盖固定 branch、namespace、catalog、runtime path、GitOps branch、Argo destination 和公网入口这些硬边界。
## 固定命名
| 对象 | v0.2 规格 |
| --- | --- |
| Source branch | `v0.2` |
| Source workspace | `G14:/root/hwlab-v02` |
| GitOps branch | `v0.2-gitops` |
| Artifact catalog | `v0.2-gitops:deploy/artifact-catalog.v02.json` |
| Runtime path | `v0.2-gitops:deploy/gitops/g14/runtime-v02` |
| Runtime namespace | `hwlab-v02` |
| Tekton Pipeline | `hwlab-ci/hwlab-v02-ci-image-publish` |
| Manual trigger | UniDesk CLI `bun scripts/cli.ts hwlab g14 control-plane trigger-current --lane v02 --confirm` |
| Scheduler/CronJob | 不创建、不保留 v02 CronJob;发布只由手动 CLI 创建 commit-pinned PipelineRun |
| Tekton ServiceAccount | `hwlab-ci/hwlab-v02-tekton-runner` |
| PipelineRun prefix | `hwlab-v02-ci-poll-<short12>` |
| Argo CD AppProject | `argocd/hwlab-v02` |
| Argo CD Application | `argocd/hwlab-g14-v02` |
| FRP Deployment | `hwlab-v02/hwlab-v02-frpc` |
| Web entry | `http://74.48.78.17:19666/` |
| API/live entry | `http://74.48.78.17:19667/health/live` |
| Git mirror/relay | 独立 `devops-infra` 集群读写服务;不设 CronJob;读 source/catalog,写 `v0.2-gitops`,按需由 UniDesk CLI 手动 sync/flush |
| Registry | 维持当前 G14 `hwlab-ci/hwlab-registry` |
`scripts/g14-gitops-render.mjs --lane v02` 是当前 `v0.2` GitOps render 入口。该 lane 必须把默认 source branch 改为 `v0.2`、GitOps branch 改为 `v0.2-gitops`、catalog 改为 `deploy/artifact-catalog.v02.json`、runtime endpoint 改为 `19667`、web endpoint 改为 `19666`,并使用完整 source commit 作为 image tag。
## 真相源
`v0.2` 的发布真相按以下顺序判断:
1. live runtime`hwlab-v02` namespace 中 Deployment/StatefulSet template、Pod ready、事件、日志和 `19666/19667` 公网 health。
2. Argo desired state`argocd/hwlab-g14-v02` 的 revision、sync、health、source branch 和 runtime path。
3. devops-infra mirror/relay 中的 GitOps branch`v0.2-gitops` 中的 `deploy/artifact-catalog.v02.json``deploy/gitops/g14/runtime-v02/**`
4. Tekton 执行证据:UniDesk `trigger-current` 返回的 PipelineRun、TaskRun result、`gitops-promote` 终态。
5. GitHub 上游归档状态:mirror/relay flush 后的 `origin/v0.2-gitops``origin/v0.2`
6. 干净 source workspace`origin/v0.2``deploy/deploy.json`、模板、render 脚本和 `--no-write` 输出。
旧 commit 记忆、`G14`/`G14-gitops` DEV/PROD 产物、D601 legacy 路径、GitHub 上游尚未 flush 的短暂落后、source branch 中历史 generated 文件和临时 worktree 只能作为线索,不能作为 `v0.2` 发布通过证据。
## Source 与 GitOps 分层
`v0.2` source branch 可以包含:
- 源码、测试、文档、人写配置和模板。
- `deploy/deploy.json` 或等价 lane 配置。
- k8s 模板、render 脚本、CI/CD helper 和 catalog schema。
`v0.2` source branch 不得跟踪:
- `deploy/artifact-catalog.v02.json`
- `deploy/gitops/g14/runtime-v02/**`
- Tekton/Argo 的 rendered runtime desired state。
- image digest、publish state、reuse evidence 或 CI 生成的 rollout metadata。
`v0.2-gitops` branch 必须包含:
- `deploy/artifact-catalog.v02.json`,记录 image tag、digest、source commit、component identity、publish/reuse 状态。
- `deploy/gitops/g14/runtime-v02/**`,作为 Argo CD 实际消费的 desired state。
- 必要的 generated metadata,但不得包含 Secret 值。
首次初始化时,如果 `v0.2-gitops:deploy/artifact-catalog.v02.json` 尚不存在,只允许由 `v0.2` lane 的正式初始化步骤创建第一版 catalog。不得 fallback 到 `G14` source catalog、`G14-gitops` catalog、DEV runtime path 或 source branch 生成物。
## CI/CD 链路
标准链路如下:
1. UniDesk CLI `hwlab g14 control-plane trigger-current --lane v02 --confirm` 解析当前 `origin/v0.2` 完整 source commit SHA,直接创建 commit-pinned `hwlab-v02-ci-poll-<short12>` PipelineRun;默认 `--dry-run` 只返回将要创建的 manifest。
2. `prepare-source` 通过 `devops-infra` mirror checkout `v0.2` source,并从 mirror 中的 `v0.2-gitops` 读取上一版 `deploy/artifact-catalog.v02.json`
3. 原语校验 task 只覆盖 repo 报告护栏、GitOps render 合同和必要的代码语法/单元检查;旧 DEV/D601/main gate 不进入 lane。
4. planner 根据 component input 判断 affected/reused services。
5. affected service 通过 BuildKit 发布到 G14 本地 registryreused service 复用 catalog digest。
6. promotion 刷新 `deploy/artifact-catalog.v02.json`render `deploy/gitops/g14/runtime-v02/**`,只推送到 `devops-infra` mirror/relay 的 `v0.2-gitops`
7. `hwlab-g14-v02` 从本地 mirror/relay 的 `v0.2-gitops:deploy/gitops/g14/runtime-v02` 同步到 `hwlab-v02`
8. UniDesk CLI 或 mirror/relay flush 操作把本地 `v0.2-gitops` 推送到 GitHub canonical remoteflush 不在 CI runtime-ready 的关键路径内,但必须可查询 pending、lastFlushed 和 failure。
9. 验收只观察 `hwlab-v02` runtime 和 `19666/19667`
`v0.2` 可以复用 G14 的 registry、proxy、BuildKit、工具镜像和脚本库;不得复用 `hwlab-g14-ci-image-publish``hwlab-g14-branch-poller``hwlab-g14-control-plane-reconciler``G14-gitops` runtime path 或 DEV/PROD Argo Application 作为 `v0.2` 发布入口。
`v0.2` 不设自动轮询发布。历史上若存在 `hwlab-v02-branch-poller``hwlab-v02-control-plane-reconciler` 或等价 CronJob,均视为迁移残留,应由 UniDesk control-plane apply 清理;后续发布、重跑、暂停和恢复都通过手动 CLI 触发或停止创建新的 PipelineRun 完成,不新增替代 CronJob。
`devops-infra` git mirror/relay 同样不设周期 CronJob。标准操作是先按需执行 `bun scripts/cli.ts hwlab g14 git-mirror sync --confirm` 把 GitHub allowlist refs 拉入本地 mirror,再执行 `bun scripts/cli.ts hwlab g14 control-plane trigger-current --lane v02 --confirm`。promotion 成功后可执行 `bun scripts/cli.ts hwlab g14 git-mirror flush --confirm` 把本地 `v0.2-gitops` 推送到 GitHub。`git-mirror apply` 维护 mirror 的 PVC、读服务、写服务、同步/flush 脚本和旧 CronJob 清理;`git-mirror sync` 创建一次性 Job,只同步 allowlist refs `v0.2``v0.2-gitops``G14``G14-gitops`,先 fetch 到隐藏 staging refs,校验 commit/tree/object closure,再用 `update-ref` 发布到公开 refs。这样 mirror read path 与 GitOps write path 都落在本地磁盘和集群网络,同时避免 CI 看到 ref 已更新但对象还不可 checkout 的半发布窗口。
写 mirror 的一致性模型是 local-first、manual-flush。promotion task 只能持有 mirror/relay 写凭证,不持有 GitHub deploy keyGitHub deploy key 只存在于 `devops-infra` mirror/relay sync/flush 边界。mirror/relay 必须在本地 receive 期间完成 object closure、目标 branch allowlist、non-fast-forward 拒绝和 changed-path 最小校验;receive 成功后本地 ref 即为 Argo 可消费事实。flush 失败不得回滚已经 rollout 的本地 GitOps revision,但必须保留 pending/outbox 状态,下一次手动 flush 可重试并输出 last error,不得静默丢弃。
## Env 容器复用与三变量启动
`v0.2` code-only fast lane 的 runtime desired state 由三类输入组成:可复用 env image digest、自动推导的 code boot metadata、以及既有 service runtime config。开发者仍按当前 DEV/OPS 流程提交 `v0.2` source commit 和维护 `deploy/deploy.json`;发布入口不得要求人工填写 repo、commitId 或 boot script 路径。
code boot metadata 固定映射到三个启动环境变量:
| 变量 | 自动推导来源 | 约束 |
| --- | --- | --- |
| `HWLAB_BOOT_REPO` | `v0.2` lane 的 canonical GitHub source repo 配置 | 必须是 canonical GitHub URL;用于身份记录,运行时读取由 resolver 自动分流到 mirror/cache。 |
| `HWLAB_BOOT_COMMIT` | UniDesk `trigger-current` 解析到的 `origin/v0.2` 完整 source commit SHA,也就是 PipelineRun revision | 必须是完整 40 位 commit SHA;禁止 branch、tag、`latest` 或人工覆盖。 |
| `HWLAB_BOOT_SH` | service model 或 `deploy/deploy.json` 中 serviceId 到 boot script 的映射,默认形态为 `deploy/runtime/boot/<serviceId>.sh` | 必须是 repo 内相对路径;禁止绝对路径、`..` 越界和从 env image 中隐式寻找旧脚本。 |
CI/CD 必须把三变量同时写入 `deploy/artifact-catalog.v02.json`、rendered workload Pod template env/annotation 和 runtime health identity。三变量是由 lane 自动推导的发布事实,不是人工 OPS 参数;如果自动推导缺失或无法证明 `HWLAB_BOOT_COMMIT` 属于 `v0.2` 允许 ancestry,本轮 promotion 必须失败。
推荐启动形态是 initContainer + `emptyDir` + generic env image。initContainer 或 env image 内的 launcher 读取三变量,通过 resolver 把 `HWLAB_BOOT_REPO` 的只读 fetch/checkout 自动分流到 `devops-infra` git mirror/cache,按 `HWLAB_BOOT_COMMIT` checkout 到 Pod 私有 `emptyDir`main container 复用同一 env image,并执行 checkout 后代码目录里的 `$HWLAB_BOOT_SH`。env image 只承载系统依赖、runtime、launcher、git client 和通用工具,不把业务代码或旧 boot script 当作运行真相。
code-only 变更时,planner 必须输出 `envChanged=false``codeChanged=true`,跳过 BuildKit image publish,复用上一版 env image digest,只更新 catalog 和 workload Pod template 中的 `HWLAB_BOOT_COMMIT`、code identity annotation 与相关 health metadata。Kubernetes 原生 Deployment/StatefulSet rolling update 仍由 Pod template hash 变化触发;不需要在容器内长期驻留 watcher,也不把 `git pull` 结果作为运行真相。
`devops-infra` git mirror/relay 是 allowlisted、PVC-backed 或等价持久化服务,负责缓存 GitHub 对象并承接 `v0.2-gitops` 本地写入。只有 mirror/relay sync/flush 边界持有 GitHub 远端凭证;`hwlab-v02`、AgentRun 和其他业务 namespace 只能访问只读 mirror/cache endpoint,不持有 GitHub deploy key。runtime checkout 失败、mirror miss 超过明确等待窗口、commit ancestry 不满足 lane 约束或 boot script 校验失败时,Pod 必须启动失败或 NotReady,不得回退到 env image 内旧代码,也不得在业务 namespace 直连 GitHub 拉取。
git mirror/relay 接入方式遵循“CI 写本地、GitHub 异步归档、读自动加速”。GitOps 和 deploy spec 中的 repo 字段仍记录 canonical GitHub URL 作为身份字段;launcher 或只读 runtime image 内的 resolver 负责读路径自动分流。需要 push `v0.2-gitops` 的 promotion task 必须 push devops-infra 本地 mirror/relay,不得在 CI 关键路径直接 push GitHub canonical remote。
registry 与 git mirror/relay 分属不同基础设施边界。registry 保持当前 G14 `hwlab-ci/hwlab-registry`,继续通过 repository prefix 服务 HWLAB、AgentRun 和后续 lane;新增 `devops-infra` git mirror/relay 不触发 registry 迁移,也不要求在 `devops-infra` 复制 registry。
## Artifact 与镜像身份
- `v0.2` 镜像 tag 使用完整 40 位 source commitId。
- runtime manifest 必须使用 digest pin 作为部署身份。
- catalog 必须记录 lane/profile、source branch、GitOps branch、source commitId、serviceId、image tag、digest、component identity 和 publish/reuse 状态;启用 env 容器复用时还必须记录 `runtimeMode=env-reuse-git-mirror-checkout``environmentImage``environmentDigest``environmentInputHash``bootRepo``bootCommit``bootSh``codeInputHash` 和三变量写入证据。
- 同一 source commit 对同一 service 应生成同一镜像;lane 差异放在 manifest、env、SecretRef、namespace、FRP 和 DB 配置中,不 bake 进镜像。
- `deploy/deploy.json` 只承载人写 runtime intent,不承载 digest、publish state 或 reuse evidence。
## Kubernetes 与 Argo 边界
- `hwlab-v02` namespace 只能由 `v0.2` GitOps lane 管理。
- `argocd/hwlab-v02` AppProject destination 只能包含 `hwlab-v02`
- `argocd/hwlab-g14-v02` source 必须指向 `devops-infra` 本地 mirror/relay 中的 `v0.2-gitops:deploy/gitops/g14/runtime-v02`destination 必须是 `hwlab-v02`
- `hwlab-v02-frpc` 只能暴露 `19666/19667`,不能复用 `17666/17667``18666/18667`
- `v0.2` Secret、DB 凭据、PVC、ServiceAccount 和 runtime config 必须独立命名或独立 namespace scope;文档、issue、trace 和 report 只记录 SecretRef 名称与 key,不记录值。
- `v0.2` 初期不新增自动 registry GC;后续如启用清理,selector 必须带 lane/profile 标签,registry digest 保护集必须同时覆盖 `G14-gitops``v0.2-gitops`
## 硬边界
以下边界是 `v0.2` CI/CD 的最小硬约束:
- source branch 必须是 `v0.2`
- GitOps branch 必须是 `v0.2-gitops`
- runtime namespace 必须是 `hwlab-v02`
- artifact catalog 必须是 `deploy/artifact-catalog.v02.json`
- runtime path 必须是 `deploy/gitops/g14/runtime-v02`
- Argo Application 必须是 `hwlab-g14-v02`,且只能部署到 `hwlab-v02`
- source branch publish 后不得出现 `deploy/artifact-catalog.v02.json``deploy/gitops/g14/runtime-v02/**` 变更。
- GitOps promotion 的 changed paths 只能落在 `deploy/artifact-catalog.v02.json``deploy/gitops/g14/runtime-v02/**` 及必要的 v02 Argo/GitOps 元数据。
- 公网验收只能使用 `19666/19667`
- `v0.2` 不得创建或依赖 CronJob`hwlab-v02-branch-poller``hwlab-v02-control-plane-reconciler` 或同类调度器出现时应清理,而不是接入发布链路。
- 旧 DEV/D601/main gate、fallback、legacy mode 和双路径兼容不得进入 `v0.2` 调用链。
- env 容器复用 fast lane 中,`HWLAB_BOOT_REPO``HWLAB_BOOT_COMMIT``HWLAB_BOOT_SH` 必须由 CI/CD 自动推导并写入 GitOps desired state,不得作为人工发布参数或 runtime 临时 patch。
- git mirror/relay 必须来自独立 `devops-infra` 服务;`hwlab-v02` runtime namespace 不部署 mirror、不持有 GitHub deploy key、不在 mirror miss 时直连 GitHub fallback。
- GitOps promotion 必须写入 `devops-infra` 本地 mirror/relay 的 `v0.2-gitops`;除 mirror/relay flush 外,不得在 CI 关键路径直接 push GitHub canonical remote。
- mirror/relay write 必须只允许 allowlist refs,拒绝 non-fast-forward,拒绝越界 changed paths,并在 receive 成功前完成 object closure 校验。
这些硬边界优先在自然写入点做最小内联断言:render 断言 namespace/runtime pathpromotion 断言 GitOps branch/changed pathsArgo spec 断言 destination,验收断言端口和 runtime identity。不要为每条设计约定再新增独立 preflight、guard、gate 或报告生成器。
## G14 DEV/PROD 不变边界
接入 `v0.2` 不得改变以下对象:
- `G14` source branch 的 poller/reconciler 语义。
- `G14-gitops` DEV/PROD catalog 与 runtime desired state。
- `hwlab-dev``hwlab-prod` namespace。
- `hwlab-g14-dev``hwlab-g14-prod` Argo Application。
- DEV `17666/17667` 与 PROD `18666/18667` FRP 入口。
- D601 legacy 回溯路径和旧运行面边界。
如果 `v0.2` 接入失败,回滚或暂停只能作用于 `hwlab-v02` lane:停止手动触发新的 v02 PipelineRun、暂停或删除 `hwlab-g14-v02`、回滚 `v0.2-gitops` runtime path、关闭 `hwlab-v02-frpc` 或清理 `hwlab-v02` namespace 资源;不得通过新增 CronJob 维持重试,也不得重启、删除或回滚 DEV/PROD 运行面。
## 验收标准
`v0.2` CI/CD 通过必须同时满足:
- `hwlab-ci` 中存在 `hwlab-v02-ci-image-publish``hwlab-v02-tekton-runner`;不存在 v02 CronJob。`hwlab-v02-branch-poller``hwlab-v02-control-plane-reconciler` 不再作为 v02 标准对象,若历史残留应由 UniDesk control-plane apply 清理。
- 最新 `v0.2` source commit 对应的 PipelineRun 完成,且 promotion 写入 `v0.2-gitops`
- `v0.2-gitops` 中存在 `deploy/artifact-catalog.v02.json``deploy/gitops/g14/runtime-v02/**`
- `argocd/hwlab-g14-v02` 指向 `devops-infra` 本地 mirror/relay 的 `v0.2-gitops:deploy/gitops/g14/runtime-v02`sync revision 与目标 GitOps revision 对齐。
- `hwlab-v02` 中长驻 workload ready,没有把 DEV/PROD namespace 当成 `v0.2` 通过证据。
- `gitops-promote` 推送本地 mirror/relay 的 `v0.2-gitops` 后应触发 `argocd/hwlab-g14-v02` hard refresh,减少 GitOps push 与 Argo 仓库发现之间的漂移窗口;refresh 触发失败只作为低噪声事件输出,最终通过仍由 `runtime-ready` 判定。
- mirror/relay status 必须能显示本地 `v0.2-gitops` revision、GitHub 已 flush revision、pending flush revision 和最近一次 flush 错误;CI 通过不要求 GitHub flush 已完成,但运维观察必须能看到上游是否落后。
- `runtime-ready` 必须以 workload Pod template 的 source commit 判断 Argo 刷新,并在 Argo 刷新超时、observer RBAC 不足或 workload 未就绪时失败;不得把 CrashLoop、未刷新或公网不可用的 runtime 标成绿色。
- 启用 env 容器复用的服务必须在 catalog、Pod template annotation/env 和 `/health/live` 或等价 runtime identity 中同时暴露 env image digest 与 `HWLAB_BOOT_REPO`/`HWLAB_BOOT_COMMIT`/`HWLAB_BOOT_SH`;只暴露镜像 digest 不能证明 code-only rollout 已生效。
- code-only rollout 的 PipelineRun 必须能证明没有发布新 env image、复用了上一版 env digest、只更新 boot commit/code identity,并由 Kubernetes Pod template hash 触发滚动。
- `devops-infra` git mirror/cache miss、commit ancestry 拒绝或 boot script 校验失败必须导致本轮 rollout fail closed,不得隐式回退到 GitHub 或 env image 内旧代码。
- `http://74.48.78.17:19666/` 返回 `v0.2` Cloud Web。
- `http://74.48.78.17:19667/health/live` 返回 `v0.2` runtime healthpayload 中的 namespace、revision 或 runtime identity 能与 `hwlab-v02`/`v0.2` 对齐。
GitOps branch 已更新、source branch render 通过、PipelineRun 名称存在或 `G14` DEV/PROD health 正常,都不能单独代表 `v0.2` CI/CD 通过。
## 测试规格
## T1
阅读 docs/reference/spec-v02-cicd.md,然后用 cli 手动测试以下内容:确认 `origin/v0.2` 最新 commit 对应的 PipelineRun 完成,promotion 只写入 `v0.2-gitops`,且 source branch 没有跟踪 `deploy/artifact-catalog.v02.json``deploy/gitops/g14/runtime-v02/**` 生成物。
## T2
阅读 docs/reference/spec-v02-cicd.md,然后用 cli 手动测试以下内容:查询 Argo `hwlab-g14-v02`,确认 source repo 为 `devops-infra` 本地 mirror/relaybranch/path 为 `v0.2-gitops:deploy/gitops/g14/runtime-v02`destination namespace 为 `hwlab-v02`sync revision 与目标 GitOps revision 对齐。
## T3
阅读 docs/reference/spec-v02-cicd.md,然后用 cli 手动测试以下内容:访问 `http://74.48.78.17:19666/``http://74.48.78.17:19667/health/live`,确认公网入口、payload environment、revision 和 runtime identity 都指向 v02,不把 DEV/PROD health 当作 v02 证据。
## T4
阅读 docs/reference/spec-v02-cicd.md,然后用 cli 手动测试以下内容:涉及 Code Agent 时使用短连接 submit/result/trace 轮询,确认 `status=completed` 且 assistant reply 非空;不得只用 `/health/live``codeAgent=ready` 证明 provider 鉴权通过。
## T5
阅读 docs/reference/spec-v02-cicd.md,然后用 cli 手动测试以下内容:对启用 env 容器复用的服务触发一次 code-only commit,确认 PipelineRun 标记 `envChanged=false`、复用上一版 env digest、catalog 与 Pod template 写入 `HWLAB_BOOT_REPO``HWLAB_BOOT_COMMIT``HWLAB_BOOT_SH`runtime health 同时暴露 env digest 和 boot commit,且 `HWLAB_BOOT_COMMIT` 来自完整 `origin/v0.2` source commit SHA。
## T6
阅读 docs/reference/spec-v02-cicd.md,然后用 cli 手动测试以下内容:在不打印任何 GitHub 凭证的前提下确认 runtime checkout 读路径命中 `devops-infra` git mirror/cache,业务 namespace 没有 GitHub deploy key;模拟 mirror miss 或非法 commit 时 rollout fail closed,不回退到 GitHub 直连或 env image 内旧代码。
## T7
阅读 docs/reference/spec-v02-cicd.md,然后用 cli 手动测试以下内容:触发一次 `v0.2` code-only promotion,确认 `gitops-promote` 只 push 到 `devops-infra` 本地 mirror/relayArgo 从本地 mirror/relay rollout;再执行 `git-mirror flush --confirm`,确认 GitHub `origin/v0.2-gitops` 快进到同一 revisionstatus 中 pending 清空。
## 规格的实现情况
| 规格项 | 状态 | 说明 |
| --- | --- | --- |
| v02 独立 source/GitOps/runtime lane | 已实现 | `v0.2``v0.2-gitops``hwlab-v02``runtime-v02` 已固定。 |
| 手动 CLI trigger/pipeline/promotion | 已实现 | 通过 UniDesk `trigger-current` 创建 commit-pinned PipelineRunv02 不设 CronJob,由 `hwlab-v02-ci-image-publish` 与 GitOps promotion 管理。 |
| v02 runtime readiness fail-closed | 已实现 | `gitops-promote` 推送后触发 Argo hard refresh`runtime-ready` 读取 workload Pod template source committimeout、observer RBAC 不足或未就绪会让 PipelineRun 失败。 |
| v02 裁撤服务不进入发布面 | 已实现 | v02 Tekton build service set、artifact catalog 和 runtime render 只包含保留服务;v02 Argo 开启 prune 清理旧 live 对象;裁撤服务仍可保留在 DEV legacy 源码中。 |
| Argo v02 Application | 已实现 | `hwlab-g14-v02` 指向 v02 GitOps path 和 namespace。 |
| FRP `19666/19667` 入口 | 已实现 | 由 `hwlab-v02-frpc` 与 master frps allowlist 共同提供。 |
| SecretRef 独立与 provider 验收 | 已实现/持续约束 | SecretRef 已独立;验收必须做真实短连接聊天。 |
| env 容器复用三变量启动 | 已实现/持续约束 | device-pod fast lane 已由 CI/CD 自动推导 `HWLAB_BOOT_REPO``HWLAB_BOOT_COMMIT``HWLAB_BOOT_SH`code-only rollout 复用 env image digest,只更新代码身份。 |
| `devops-infra` git mirror/relay 加速 | 部分实现/待迁移写路径 | source/catalog/runtime checkout 读路径已使用独立基础设施集群 mirror/cache;下一步必须把 GitOps promotion、Argo source 和 GitHub flush 收敛到真正写 mirror。runtime namespace 不持有 GitHub deploy keyregistry 保持 G14 `hwlab-ci/hwlab-registry`mirror 同步和 flush 由 UniDesk CLI 手动触发,不设置 CronJob。 |
| 自动 registry GC | 未实现 | 初期不启用自动 GC,后续需 lane/profile 保护集。 |
## 平行 lane 运维边界
后续新增 `v0.x` 或其他平行 runtime lane 时,优先复用本节的判定顺序和排障边界,避免把一次性补丁沉淀成新的宽泛门禁。本节只保留可复用的运维边界;具体执行记录、排障流水和一次性证据应放在 issue 或 PR 中。
### Secret 导入与重启边界
平行 lane 的 Secret 必须独立命名,不能在 runtime 里直接引用 DEV Secret。允许把 DEV 当前值一次性导入到目标 lane 的独立 Secret 名,但验证只能输出 Secret 对象、key、字节数和哈希指纹,不能打印 Secret value、token 片段、完整 DB URL 或 `auth.json` 内容。
`v0.2` 至少需要独立维护以下 SecretRef:
- `hwlab-v02-postgres/POSTGRES_PASSWORD`
- `hwlab-cloud-api-v02-db/database-url`
- `hwlab-v02-code-agent-provider/openai-api-key`
- `hwlab-v02-code-agent-codex-auth/auth.json`
Code Agent 的 Secret 修复不是只改一个 Secret 对象就结束。`hwlab-cloud-api` 通过 env 读取 `OPENAI_API_KEY`Secret 更新后必须滚动 `hwlab-v02/hwlab-cloud-api`。DeepSeek profile 还通过 `hwlab-deepseek-proxy` 的 initContainer 把 `DEEPSEEK_API_KEY` 渲染进 Moon Bridge 配置,Secret 更新后也必须滚动 `hwlab-v02/hwlab-deepseek-proxy`,否则 proxy 仍会使用旧配置并返回上游鉴权失败。
### Code Agent 验收
`/health/live``codeAgent=ready``codexStdio=ready` 只能证明运行时结构、二进制、workspace、token boundary 和会话 supervisor 就绪;它不证明真实 provider 鉴权可用。涉及 Code Agent 的扩容验收必须追加一次真实短连接聊天闭环:用 `Prefer: respond-async``X-HWLAB-Short-Connection: 1` 提交 `/v1/agent/chat`,再轮询 `/v1/agent/chat/result/<traceId>`,只有 `status=completed` 且 assistant reply 非空才算通过。
如果 trace 里出现 `Authentication Fails``upstream stream error``codex_stdio_provider_retry`,先按 profile 分层判断:`deepseek` profile 走 `hwlab-deepseek-proxy.<namespace>.svc.cluster.local:4000/v1/responses` 和 Moon Bridge`codex-api` profile 走 Pod-local loopback forwarder。不要用 `codex-api` readiness 掩盖 DeepSeek 专用凭证或 Moon Bridge 配置问题。
长耗时 smoke 不应通过 UniDesk SSH 长连接等待完整 Codex turn。Codex 首 token 可能超过短查询窗口,验证应使用短连接 submit/result/trace 轮询,避免把控制通道超时误判成 provider 失败。
### GitOps 与 runtime 收敛
GitOps promotion 成功不等于 runtime 已经运行新版本。验收必须等待 `argocd/hwlab-g14-v02` 的 sync revision 对齐最新 `v0.2-gitops` revision,并确认 `19667/health/live``environment``endpoint`、关键 SecretRef 和 service revision 与目标 lane 对齐。
Argo `Synced/Healthy` 也不能单独替代公网验证。FRP server 侧 `allowPorts` 缺失时,`hwlab-v02-frpc` 会反复报告 `port not allowed`;这种问题应修 master 侧 `frps` allowlist 并只重启 `hwlab-frps-dev`,不要改 DEV/PROD GitOps、Service 或 v02 runtime path。修复后必须同时验证新增 `19666/19667` 和既有 DEV `17666/17667`
### 后续扩容建议
下一条平行 lane 建议先列一张最小资源映射表,再落地 CI/CDsource branch、GitOps branch、runtime namespace、runtime path、Argo Application、FRP ports、artifact catalog、Postgres Secret、Cloud API DB Secret、Code Agent provider Secret、Codex auth Secret、DeepSeek proxy restart 对象和公网验收 URL。映射表是执行清单,不是新 gate;只有 branch、namespace、runtime path、GitOps branch、Argo destination、SecretRef 名称和公网端口这些硬边界需要内联断言。
Secret、FRP 和 Argo 问题都应先在目标运行面做最小真实闭环,再进入完整 CI/CD 复跑。不要用完整 PipelineRun 反复探索 Secret 值、FRP allowlist 或 provider 鉴权;CI/CD 只负责固化已经在目标 namespace 证明可行的配置和源码。