diff --git a/docs/reference/spec-v02-cicd.md b/docs/reference/spec-v02-cicd.md index ef7bf383..25849d0b 100644 --- a/docs/reference/spec-v02-cicd.md +++ b/docs/reference/spec-v02-cicd.md @@ -107,7 +107,7 @@ CI/CD 内部由 UniDesk 手动触发入口、PipelineRun、component planner、B `v0.2` 不设自动轮询发布。历史上若存在 `hwlab-v02-branch-poller`、`hwlab-v02-control-plane-reconciler` 或等价 CronJob,均视为迁移残留,应由 UniDesk control-plane apply 清理;后续发布、重跑、暂停和恢复都通过手动 CLI 触发或停止创建新的 PipelineRun 完成,不新增替代 CronJob。 -`devops-infra` git mirror/cache 同样不设周期 CronJob。标准操作是先按需执行 `bun scripts/cli.ts hwlab g14 git-mirror sync --confirm`,再执行 `bun scripts/cli.ts hwlab g14 control-plane trigger-current --lane v02 --confirm`。`git-mirror apply` 只维护 mirror 的 PVC、只读 HTTP 服务、同步脚本和旧 CronJob 清理;`git-mirror sync` 创建一次性 Job,先把 GitHub refs fetch 到隐藏 staging refs,校验 commit/tree/object closure,再用 `update-ref` 发布到公开 refs。这样 mirror read path 仍是本地磁盘速度,同时避免 CI 看到 ref 已更新但对象还不可 checkout 的半发布窗口。 +`devops-infra` git mirror/cache 同样不设周期 CronJob。标准操作是先按需执行 `bun scripts/cli.ts hwlab g14 git-mirror sync --confirm`,再执行 `bun scripts/cli.ts hwlab g14 control-plane trigger-current --lane v02 --confirm`。`git-mirror apply` 只维护 mirror 的 PVC、只读 HTTP 服务、同步脚本和旧 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 仍是本地磁盘速度,同时避免 CI 看到 ref 已更新但对象还不可 checkout 的半发布窗口。 ## Env 容器复用与三变量启动 diff --git a/scripts/g14-gitops-render.mjs b/scripts/g14-gitops-render.mjs index 0fdefa2f..749c0d82 100644 --- a/scripts/g14-gitops-render.mjs +++ b/scripts/g14-gitops-render.mjs @@ -2826,8 +2826,10 @@ else fi git -C "$repo_path" config uploadpack.hideRefs refs/mirror-stage git -C "$repo_path" config --unset-all remote.origin.fetch 2>/dev/null || true -git -C "$repo_path" config --add remote.origin.fetch '+refs/heads/*:refs/mirror-stage/heads/*' -git -C "$repo_path" config --add remote.origin.fetch '+refs/tags/*:refs/mirror-stage/tags/*' +git -C "$repo_path" config --add remote.origin.fetch '+refs/heads/v0.2:refs/mirror-stage/heads/v0.2' +git -C "$repo_path" config --add remote.origin.fetch '+refs/heads/v0.2-gitops:refs/mirror-stage/heads/v0.2-gitops' +git -C "$repo_path" config --add remote.origin.fetch '+refs/heads/G14:refs/mirror-stage/heads/G14' +git -C "$repo_path" config --add remote.origin.fetch '+refs/heads/G14-gitops:refs/mirror-stage/heads/G14-gitops' timeout 180 git -C "$repo_path" fetch --quiet --prune origin git -C "$repo_path" for-each-ref --format='%(objectname) %(refname)' refs/mirror-stage/heads > /tmp/hwlab-stage-heads git -C "$repo_path" for-each-ref --format='%(refname)' refs/mirror-stage/heads > /tmp/hwlab-stage-head-refs @@ -2837,6 +2839,9 @@ if [ ! -s /tmp/hwlab-stage-heads ]; then echo "git mirror sync fetched no branch refs" >&2 exit 41 fi +for required_ref in refs/mirror-stage/heads/v0.2 refs/mirror-stage/heads/v0.2-gitops refs/mirror-stage/heads/G14 refs/mirror-stage/heads/G14-gitops; do + git -C "$repo_path" show-ref --verify --quiet "$required_ref" || { echo "git mirror sync missing required ref $required_ref" >&2; exit 43; } +done while read -r sha ref; do [ -n "$sha" ] || continue git -C "$repo_path" cat-file -e "$sha^{commit}" diff --git a/scripts/g14-gitops-render.test.ts b/scripts/g14-gitops-render.test.ts index f7c74bcb..8e91ce27 100644 --- a/scripts/g14-gitops-render.test.ts +++ b/scripts/g14-gitops-render.test.ts @@ -87,7 +87,11 @@ test("v02 render follows TypeScript runtime checks and does not self-patch boots assert.doesNotMatch(gitMirror, /"name": "git-mirror-hwlab-sync"/u); const gitMirrorJson = JSON.parse(gitMirror); const gitMirrorScript = gitMirrorJson.items.find((item) => item.kind === "ConfigMap" && item.metadata?.name === "git-mirror-sync-script")?.data?.["sync.sh"] ?? ""; - assert.match(gitMirrorScript, /refs\/mirror-stage\/heads\/\*/u); + assert.match(gitMirrorScript, /refs\/heads\/v0\.2:refs\/mirror-stage\/heads\/v0\.2/u); + assert.match(gitMirrorScript, /refs\/heads\/v0\.2-gitops:refs\/mirror-stage\/heads\/v0\.2-gitops/u); + assert.match(gitMirrorScript, /refs\/heads\/G14:refs\/mirror-stage\/heads\/G14/u); + assert.match(gitMirrorScript, /refs\/heads\/G14-gitops:refs\/mirror-stage\/heads\/G14-gitops/u); + assert.doesNotMatch(gitMirrorScript, /refs\/heads\/\*:refs\/mirror-stage\/heads\/\*/u); assert.match(gitMirrorScript, /git -C "\$repo_path" update-ref "refs\/heads\/\$name" "\$sha"/u); assert.ok((gitMirrorJson.items || []).every((item) => item.kind !== "Secret")); assert.ok((gitMirrorJson.items || []).every((item) => item.kind !== "CronJob"));