From d6cd14f260fb6640368c1b6e1d359623f7960151 Mon Sep 17 00:00:00 2001 From: Codex Agent Date: Thu, 4 Jun 2026 22:45:37 +0800 Subject: [PATCH] fix(v02): make cd latest-only --- docs/reference/spec-v02-cicd.md | 17 +++++++++-------- scripts/g14-gitops-render.mjs | 3 ++- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/docs/reference/spec-v02-cicd.md b/docs/reference/spec-v02-cicd.md index bbd182b9..58996f3e 100644 --- a/docs/reference/spec-v02-cicd.md +++ b/docs/reference/spec-v02-cicd.md @@ -2,7 +2,7 @@ 本文是 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),PR 合并后自动 CD 迁移计划见 [pikasTech/HWLAB#848](https://github.com/pikasTech/HWLAB/issues/848)。原 `docs/plan/hwlab-v02-namespace-cicd.md` 阶段计划全文已迁入 #530 评论。本文只记录稳定规格、边界和判定标准;不要把一次性执行记录、排障流水账或临时证据写入本文。 +实施跟踪见 [pikasTech/HWLAB#530](https://github.com/pikasTech/HWLAB/issues/530),env 容器复用、三变量启动和 git mirror 加速设计见 [pikasTech/HWLAB#572](https://github.com/pikasTech/HWLAB/issues/572),PR 合并后自动 CD 迁移计划见 [pikasTech/HWLAB#848](https://github.com/pikasTech/HWLAB/issues/848),CI 无锁并发与 CD latest-only 迁移见 [pikasTech/HWLAB#866](https://github.com/pikasTech/HWLAB/issues/866)。原 `docs/plan/hwlab-v02-namespace-cicd.md` 阶段计划全文已迁入 #530 评论。本文只记录稳定规格、边界和判定标准;不要把一次性执行记录、排障流水账或临时证据写入本文。 ## 在系统中的职责划分 @@ -114,8 +114,8 @@ devops-infra git mirror 仍是 PipelineRun 和 Argo CD 的集群内读写源。` 标准链路如下: 1. PR open/update 阶段只运行 source CI、检查和 PR preflight,不修改 `hwlab-v02` runtime,也不写 `v0.2-gitops`。 -2. UniDesk CLI v02 PR monitor 只观察 `pikasTech/HWLAB` base=`v0.2` 的 ready PR;merge 成功后重新 fetch `/root/hwlab-v02-cicd.git` 的 `origin/v0.2`,以 fetch 后的完整 source commit SHA 作为待发布目标。 -3. monitor 调用现有 `hwlab g14 control-plane trigger-current --lane v02 --confirm`。该入口自动复核 `devops-infra` mirror 的 `localV02` ref,必要时执行一次 bounded `git-mirror sync` Job,再创建 commit-pinned `hwlab-v02-ci-poll-` PipelineRun;默认 `--dry-run` 只返回将要创建的 manifest 和 mirror pre-sync 计划。人工重跑和 `auto-cd --once` 补偿必须复用同一入口,不得直接创建 PipelineRun。 +2. UniDesk CLI v02 PR monitor 只观察 `pikasTech/HWLAB` base=`v0.2` 的 ready PR;ready PR 不因为其他 commit 的 PipelineRun 仍在运行而阻塞 merge。merge 成功后重新 fetch `/root/hwlab-v02-cicd.git` 的 `origin/v0.2`,以 fetch 后的完整 source commit SHA 作为待发布目标。 +3. monitor 调用现有 `hwlab g14 control-plane trigger-current --lane v02 --confirm`。该入口自动复核 `devops-infra` mirror 的 `localV02` ref,必要时执行一次 bounded `git-mirror sync` Job,再创建 commit-pinned `hwlab-v02-ci-poll-` PipelineRun;同一 source commit 已有 PipelineRun 时只复用现有状态,不删除重建。默认 `--dry-run` 只返回将要创建的 manifest 和 mirror pre-sync 计划。人工重跑和 `auto-cd --once` 补偿必须复用同一入口,不得直接创建 PipelineRun。 4. `prepare-source` 通过 `devops-infra` mirror checkout `v0.2` source,并从 mirror 中的 `v0.2-gitops` 读取上一版 `deploy/artifact-catalog.v02.json`。 5. CI/CD 校验只保留最小构建、TypeScript 语义检查、自动单元测试、打包和必要冒烟检查;旧 DEV/D601/main gate、运行时内部证明型校验、健康诊断重断言和历史预检不进入 lane。 6. planner 根据 component input 判断 affected/reused services。 @@ -126,9 +126,9 @@ devops-infra git mirror 仍是 PipelineRun 和 Argo CD 的集群内读写源。` 只有 package/runtime/env 输入变化时才构建 `-env` 镜像。 纯前端源码、Device Pod 源码或 boot code 变化只更新三变量和 GitOps desired state, 不再重新构建业务镜像。 -8. promotion 刷新 `deploy/artifact-catalog.v02.json`,render `deploy/gitops/g14/runtime-v02/**`,只推送到 `devops-infra` mirror/relay 的 `v0.2-gitops`。 +8. promotion 刷新 `deploy/artifact-catalog.v02.json`,render `deploy/gitops/g14/runtime-v02/**`,只在本 PipelineRun 的 source commit 仍是当前 `origin/v0.2` head 时推送到 `devops-infra` mirror/relay 的 `v0.2-gitops`;若 source branch 已推进,本轮输出 superseded/no-op,写出 `runtime-ready-required=false`,不得回写旧 GitOps revision。 9. `hwlab-g14-v02` 从本地 mirror/relay 的 `v0.2-gitops:deploy/gitops/g14/runtime-v02` 同步到 `hwlab-v02`。 -10. UniDesk CLI auto-CD 观察定点 `control-plane status --lane v02 --source-commit ` 或 `--pipeline-run `,确认 PipelineRun、Argo、runtime workload、public probes 和 planArtifacts build/reuse 摘要。 +10. UniDesk CLI auto-CD 观察定点 `control-plane status --lane v02 --source-commit ` 或 `--pipeline-run `,确认 PipelineRun、Argo、runtime workload、public probes 和 planArtifacts build/reuse 摘要。历史 merge head 若因后续 `origin/v0.2` 推进而被 superseded,PR 评论以 superseded 收口;最新 head 仍必须继续收敛到 runtime。 11. UniDesk CLI 或 mirror/relay flush 操作把本地 `v0.2-gitops` 推送到 GitHub canonical remote;flush 不在 CI runtime-ready 的关键路径内,但自动 CD 收口必须查询 pending、lastFlushed 和 failure,必要时执行 `git-mirror flush --confirm` 并等待 `pendingFlush=false`。 12. 验收只观察 `hwlab-v02` runtime 和 `19666/19667`,并把 source commit、PipelineRun、GitOps revision、build/reuse 摘要、Argo/runtime/public probe 状态写回 PR 或关联 issue。 @@ -142,7 +142,7 @@ GitOps promotion 成功后,本地 mirror/relay 的 `v0.2-gitops` 可立即被 `v0.2` 不设 k8s 自动轮询发布。历史上若存在 `hwlab-v02-branch-poller`、`hwlab-v02-control-plane-reconciler` 或等价 CronJob,均视为迁移残留,应由 UniDesk control-plane apply 清理。PR 合并后的自动 CD 只能由 UniDesk CLI monitor 或一次性 reconcile job 驱动,并且必须复用 `trigger-current`、定点 `status` 和 `git-mirror flush`。暂停发布时停止 UniDesk monitor 或停止创建新的 PipelineRun;不要通过新增 CronJob 维持重试。 -v02 auto-CD 必须有 lane 级互斥与补偿语义。同一个 source commit 已有运行中或成功 PipelineRun 时不得重复创建;旧 run 仍在运行时如果 `origin/v0.2` 又推进,只记录最新 pending head,等待旧 run 结束后再部署最新 head。`auto-cd --once` 或等价补偿入口用于处理人工 GitHub merge、直接 push、monitor 重启或上次触发失败:它比较 `origin/v0.2` head、PipelineRun、Argo/GitOps 和 mirror flush 状态,缺什么补什么,但仍不绕过标准 control-plane 入口。 +v02 auto-CD 必须采用 CI 无锁并发与 CD latest-only 语义。不同 source commit 的 PipelineRun 可以并发运行;monitor 不等待旧 run 空闲,也不取消旧 run。同一个 source commit 已有 PipelineRun 时不得删除重建。GitOps promotion 是唯一写入点,必须在写 `v0.2-gitops` 前重新读取 `origin/v0.2` head:只有当前 PipelineRun commit 仍是最新 head 才允许写入;旧 commit 继续跑完 CI 后必须 superseded/no-op 收口,不能把 runtime 或 GitOps branch 滚回旧 commit。`auto-cd --once` 或等价补偿入口用于处理人工 GitHub merge、直接 push、monitor 重启或上次触发失败:它比较最新 `origin/v0.2` head、PipelineRun、Argo/GitOps 和 mirror flush 状态,缺什么补什么,但仍不绕过标准 control-plane 入口。 `devops-infra` git mirror/relay 同样不设周期 CronJob。标准触发命令 `bun scripts/cli.ts hwlab g14 control-plane trigger-current --lane v02 --confirm` 会在创建 PipelineRun 前按需同步 mirror;`bun scripts/cli.ts hwlab g14 git-mirror sync --confirm` 只作为显式 mirror 维护或诊断入口。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 的半发布窗口。 @@ -532,8 +532,9 @@ registry 与 git mirror/relay 分属不同基础设施边界。registry 保持 `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 清理。 -- base=`v0.2` 的 ready PR 由 UniDesk CLI 合并后,会自动触发对应 merge head 的 v02 PipelineRun;同一个 source commit 已有运行中或成功 PipelineRun 时不重复创建。 -- 自动 CD 在旧 run 运行期间遇到新 `origin/v0.2` head 时,只保留最新 pending head,旧 run 收口后再部署最新 head,避免并行 PipelineRun 同时争用 `v0.2-gitops`。 +- base=`v0.2` 的 ready PR 由 UniDesk CLI 合并后,会自动触发对应 merge head 的 v02 PipelineRun;其他 commit 的运行中 PipelineRun 不阻塞 ready PR merge 或 CI 启动。 +- 同一个 source commit 已有 PipelineRun 时不重复创建,也不删除重建;失败 run 的人工重试必须走后续显式 retry 策略,不恢复默认 delete/create。 +- 自动 CD 在旧 run 运行期间遇到新 `origin/v0.2` head 时,新 head 可直接触发自己的 PipelineRun;旧 run 继续完成 CI,但 promotion 必须在写 GitOps 前发现 stale head 并 superseded/no-op,不能回写旧 `v0.2-gitops` 或回滚 runtime。 - 最新 `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 对齐。 diff --git a/scripts/g14-gitops-render.mjs b/scripts/g14-gitops-render.mjs index 20b7da00..e7dc719f 100644 --- a/scripts/g14-gitops-render.mjs +++ b/scripts/g14-gitops-render.mjs @@ -1546,7 +1546,8 @@ check_source_head() { exit 1 fi if [ "$latest" != "$expected" ]; then - echo '{"status":"skipped-stale-source","phase":"'"$phase"'","sourceBranch":"'"$(params.source-branch)"'","sourceRevision":"'"$(params.revision)"'","expectedRevision":"'"$expected"'","latestRevision":"'"$latest"'"}' + printf 'false' > /tekton/results/runtime-ready-required || true + echo '{"status":"skipped-stale-source","verdict":"superseded","phase":"'"$phase"'","sourceBranch":"'"$(params.source-branch)"'","sourceRevision":"'"$(params.revision)"'","expectedRevision":"'"$expected"'","latestRevision":"'"$latest"'"}' exit 0 fi }