fix: improve hwlab v02 status targeting
This commit is contained in:
@@ -44,7 +44,7 @@ CI/CD、GitOps、rollout、artifact 发布、PR 合并后的 DEV/PROD 滚动、P
|
||||
- `commander contract|plan --dry-run|smoke --dry-run|approval request --dry-run|prompt-lint --kind gpt55-pr` 是 host Codex 指挥官直管微服务 skeleton 入口。当前命令返回 `phase=source-contract`、service/API/state/bridge/prompt/trace/#20/#46/ClaudeQQ 审批边界、.state/commander/ 状态模型、dev 无 daemon smoke contract、dry-run 计划和 GPT-5.5 PR prompt 边界辅助 lint,不接 live bridge、不注入 prompt、不发送 ClaudeQQ。`approval request --dry-run` 会生成 200 字以内中文纯文本 ClaudeQQ 审批草案、`notification-path-unavailable` blocker 和授权后唯一可用的 `bun scripts/cli.ts microservice proxy claudeqq /api/push/text --method POST --body-json '<payload>' --raw` 命令;不得提示使用本机 ClaudeQQ skill、powershell 或本地 server。`prompt-lint` 支持 `--prompt-file` 与 `--stdin`,输出 `ok`、`missingClauses`、`riskLevel`、`suggestedPatchSnippet` 且不回显完整 prompt;它是 commander 辅助检查,不是业务 PR 门禁,也不改变 `codex submit` 默认行为。`plan`、`smoke` 与 `approval request` 必须带 `--dry-run`;缺少时返回 `error=dry-run-required`。长期规则见 `docs/reference/host-codex-commander.md`。
|
||||
- `hwlab g14 monitor-prs [--once] [--dry-run] [--interval-seconds N] [--max-cycles N] [--timeout-seconds N]` 是当前 HWLAB G14 PR -> CI/CD -> DEV rollout 的一行式入口。普通调用创建 `.state/jobs/` 异步 job 并立刻返回 `job.id`、`statusCommand` 和 stdout/stderr 路径;后台 worker 每轮通过 UniDesk `gh pr list/preflight/merge` 监控 `pikasTech/HWLAB` base=`G14` 的 open PR,ready 时合并,然后通过 UniDesk `ssh G14:k3s` 观察 `hwlab-g14-ci-poll-<short>`、Argo `hwlab-g14-dev` 和 DEV `/health/live`,直到 DEV `Synced/Healthy` 且 Deployment/StatefulSet ready;历史 `Completed` smoke/debug pod 不作为 rollout blocker。每次成功 DEV rollout 后,worker 会定位或创建 #7“指挥简报索引”中的北京日期每日简报 issue,并追加 CI/CD 耗时、CI/CD 关键指标、语义化上线 changelog、自动 diff 摘要、PipelineRun、GitOps revision 和 DEV 验证摘要;关键指标来自 G14 Tekton TaskRun results,固定包含 `lazy build reused: x/y`、reused services、rebuild services 和每个 service 的独立耗时/状态/backend,用于观察 lazy build 机制效果。语义化 changelog 优先从 PR body 的 `## 修改`/`## 变更`/`## Changelog` 等段落提取,diff 摘要只作为文件和统计证据保留,不替代 changelog。也可用 `hwlab g14 record-rollout --pr <number> --source-commit <sha>` 手动补记,手动补记同样会按 PipelineRun 采集 TaskRun 指标。状态指针按用途分离:长期监控只写 `.state/hwlab-g14/latest-monitor-job.json`,`--once` 写 `latest-once-job.json`,`--dry-run` 写 `latest-dry-run-job.json`,`--once --dry-run` 写 `latest-once-dry-run-job.json`,避免一次性收口覆盖持续监控入口。`--once --dry-run` 只做单轮监控和 merge plan,不写 GitHub、不等待 rollout。该命令禁止使用原生 `gh` 或手拼 GitHub 请求;如果 UniDesk `gh` 子命令字段或行为不够,必须先改进 `scripts/src/gh.ts` 后再使用。
|
||||
- `agentrun v01 control-plane status|trigger-current|refresh [--dry-run|--confirm]` 是 AgentRun `v0.1` 在 G14 k3s 的受控 Tekton/Argo 入口。`status` 只读汇总固定 source worktree commit、对应 commit-pinned PipelineRun、GitOps latest、Argo Application 和 `agentrun-v01` workload,并报告 Argo revision 是否对齐 `v0.1-gitops` latest;`trigger-current` 先快进 `G14:/root/agentrun-v01` 到 `origin/v0.1`,再创建 `agentrun-v01-ci-<short12>` PipelineRun。confirmed trigger 只提交 CI/CD 工作并返回后续 `status` 命令,不等待完整 PipelineRun;同名 PipelineRun 运行中或已成功时拒绝重复触发,只允许失败态重建或首次创建。`refresh` 只对 `argocd/agentrun-g14-v01` 执行 hard refresh,用于 GitOps promotion 已完成但 Argo 仍停留旧 revision 时的受控同步入口;它不直接 patch runtime workload。AgentRun 运行时和 SPEC 事实来源仍在 AgentRun 仓库,UniDesk 只维护受控运维入口。
|
||||
- `hwlab g14 control-plane status|apply --lane v02 [--dry-run|--confirm]` 是 HWLAB `v0.2` 加法 lane 的受控 Tekton/Argo 控制面维护入口,source commit 只来自 G14 专用 bare repo `/root/hwlab-v02-cicd.git` 的 `refs/remotes/origin/v0.2`;`/root/hwlab-v02` 只作为人工开发和短连接源码工具 workspace 被观测,dirty/stale 状态必须输出为 isolated warning 而不能阻塞 CI/CD。该入口面向 branch `v0.2`、namespace `hwlab-ci` 和 Argo application `hwlab-g14-v02`;`status` 只读汇总 pipeline、RBAC/ServiceAccount、Argo、当前 commit PipelineRun、当前 PipelineRun 的 TaskRun 条件摘要、最近 PipelineRun 摘要、活跃 PipelineRun、遗留 v02 CronJob 清理状态、commit alignment,以及 19666/19667 的 Cloud Web 静态资源和 API live 探针。TaskRun 摘要的 `performance` 字段会把超过 120s 的 build TaskRun 标为慢任务、超过 180s 标为 critical warning,用于暴露 env reuse/git mirror 命中率回归,但不作为阻断门禁。`webAssets` 必须直接给出 `readonly-rpc` 删除、sidebar/workspace/event panel 关键 CSS、`/app.js` 是否可读取和字节数、`/health/live` 与 API revision;`apiRevision` 是 cloud-api 服务自身 revision,Cloud Web 静态资源变更时允许它与 source commit 不同,不能把这种差异误判成 Cloud Web 未发布。默认只读取必要字段,禁止把完整 PipelineRun spec、Tekton 内联脚本、历史大对象或整份 CSS/HTML/JS 展开到默认输出;`apply` 先自动 fetch `/root/hwlab-v02-cicd.git` 并从 commit-pinned detached worktree 执行 render check,再经 `G14:k3s` server-side apply `tekton-v02/rbac.yaml`、`pipeline.yaml`、`argocd/project.yaml` 和 `argocd/application-v02.yaml`,confirmed apply 会删除遗留 v02 CronJob,但不会应用 runtime-v02 workload、Secret 或数据迁移。
|
||||
- `hwlab g14 control-plane status|apply --lane v02 [--dry-run|--confirm]` 是 HWLAB `v0.2` 加法 lane 的受控 Tekton/Argo 控制面维护入口,source commit 只来自 G14 专用 bare repo `/root/hwlab-v02-cicd.git` 的 `refs/remotes/origin/v0.2`;`/root/hwlab-v02` 只作为人工开发和短连接源码工具 workspace 被观测,dirty/stale 状态必须输出为 isolated warning 而不能阻塞 CI/CD。该入口面向 branch `v0.2`、namespace `hwlab-ci` 和 Argo application `hwlab-g14-v02`;默认 `status` 只读汇总最新 source head 的 pipeline、RBAC/ServiceAccount、Argo、当前 commit PipelineRun、当前 PipelineRun 的 TaskRun 条件摘要、最近 PipelineRun 摘要、活跃 PipelineRun、遗留 v02 CronJob 清理状态、commit alignment,以及 19666/19667 的 Cloud Web 静态资源和 API live 探针。分支被后续提交推进后,要复查已完成 run 时使用 `status --lane v02 --pipeline-run hwlab-v02-ci-poll-<short-sha>`;已知完整 source SHA 但不想依赖最新 head 时使用 `status --lane v02 --source-commit <full-sha>`。定点 `status` 输出 `statusTarget.mode`,只检查指定 PipelineRun/source commit 的证据,不因为 `origin/v0.2` 后续推进而把历史 run 判为失败;默认不带定点参数时仍严格判定最新 source head alignment。TaskRun 摘要的 `performance` 字段会把超过 120s 的 build TaskRun 标为慢任务、超过 180s 标为 critical warning,用于暴露 env reuse/git mirror 命中率回归,但不作为阻断门禁;CI/CD 性能验收应同时看 `planArtifacts.summary`、`taskRuns.performance.warningCount` 和 PipelineRun duration,纯 CLI/文档或无 runtime 重建需求的后续提交应稳定表现为 `build=0 reuse=<service-count>` 且无 build TaskRun warning,首次引入或切换 env image 时允许只构建必要 env image 一次。`webAssets` 必须直接给出 `readonly-rpc` 删除、sidebar/workspace/event panel 关键 CSS、`/app.js` 是否可读取和字节数、`/health/live` 与 API revision;`apiRevision` 是 cloud-api 服务自身 revision,Cloud Web 静态资源变更时允许它与 source commit 不同,不能把这种差异误判成 Cloud Web 未发布。默认只读取必要字段,禁止把完整 PipelineRun spec、Tekton 内联脚本、历史大对象或整份 CSS/HTML/JS 展开到默认输出;`apply` 先自动 fetch `/root/hwlab-v02-cicd.git` 并从 commit-pinned detached worktree 执行 render check,再经 `G14:k3s` server-side apply `tekton-v02/rbac.yaml`、`pipeline.yaml`、`argocd/project.yaml` 和 `argocd/application-v02.yaml`,confirmed apply 会删除遗留 v02 CronJob,但不会应用 runtime-v02 workload、Secret 或数据迁移。
|
||||
- `hwlab g14 control-plane trigger-current --lane v02 [--dry-run|--confirm]` 是 v02 标准手动触发入口:先自动 fetch `/root/hwlab-v02-cicd.git`,解析当前 `origin/v0.2` full SHA,创建 commit-pinned `hwlab-v02-ci-poll-<short12>` PipelineRun;读 Git 走 `git-mirror-http.devops-infra.svc.cluster.local`,GitOps promotion 写 `git-mirror-write.devops-infra.svc.cluster.local`;confirmed trigger 在删除/创建 PipelineRun 前会先按当前 source commit 在 G14 临时 detached worktree 中 render,再 server-side apply v02 Tekton RBAC、Pipeline 与 Argo Application,避免 CI/CD 脚本或 runtime-ready 逻辑已合并但集群仍执行旧 Pipeline 定义;该 render 不要求固定 `/root/hwlab-v02` 工作树 clean,也不得因 `.worktree/` 或其他并行未提交修改阻塞;同名 PipelineRun 成功或运行中时拒绝重复触发,失败或不存在时才删除旧对象并重新创建。
|
||||
创建 PipelineRun 前会读取 `devops-infra` mirror refs,若 `localV02` 未等于当前 source commit,则自动执行一次受控 manual `git-mirror sync` Job 并复核 ref,复核失败时停止触发,避免 Tekton `prepare-source` 已知失败;services 参数只包含 v02 runtime service matrix,`hwlab-cli` 是固定 repo 短连接源码工具,不进入 PipelineRun service build。
|
||||
`--dry-run` 只报告是否会 pre-sync,不创建 Job;confirmed trigger 默认创建 `.state/jobs/` 异步 job 并立刻返回 `job.id`、`statusCommand`、stdout/stderr 路径,避免 git mirror pre-sync 或 PipelineRun 创建期间长时间阻塞;`--wait` 路径也必须向 stderr 输出 `hwlab.v02.trigger.progress` JSON 事件,覆盖 `control-plane-refresh`、`git-mirror-pre-sync`、`delete-existing-pipelinerun` 和 `create-pipelinerun`,避免异步 job 长时间只有启动命令而无法判断卡点;默认 JSON 必须对 `manifest_b64`、长脚本和远端 stdout/stderr 做有界摘要,保留长度与 hash,最终 trigger 结果只返回阶段摘要和关键 tail,完整内容通过 job stdout/stderr 文件渐进披露;只有现场同步调试才显式加 `--wait`;旧 `rerun-current` 只作为输入别名保留。PipelineRun `Completed`、Argo `Synced/Healthy` 和 `webAssets.ok=true` 只证明 G14 runtime 已更新;交付收口还必须用 `hwlab g14 git-mirror status` 查看 `cache.summary.pendingFlush`,若为 true,继续执行受控 `hwlab g14 git-mirror flush --confirm` 并用 job status 轮询到 `pendingFlush=false`。
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { gitMirrorFlushJobManifest, gitMirrorStatusSummary, gitMirrorSyncJobManifest, gitMirrorV02SyncRequirement, hwlabG14MonitorStateFileName, parseGitMirrorStatusRefs, parsePipelineTaskRunMetrics, rolloutRecordBody, semanticChangelogBullets, v02CommitAlignment, v02ControlPlaneRenderScript, v02FalseGreenGuard, v02PipelineServiceIds, v02TaskRunPerformanceSummary } from "./src/hwlab-g14";
|
||||
import { gitMirrorFlushJobManifest, gitMirrorStatusSummary, gitMirrorSyncJobManifest, gitMirrorV02SyncRequirement, hwlabG14Help, hwlabG14MonitorStateFileName, parseGitMirrorStatusRefs, parsePipelineTaskRunMetrics, rolloutRecordBody, semanticChangelogBullets, v02CommitAlignment, v02ControlPlaneRenderScript, v02FalseGreenGuard, v02PipelineServiceIds, v02TaskRunPerformanceSummary } from "./src/hwlab-g14";
|
||||
|
||||
function assertCondition(condition: unknown, message: string, detail: unknown = {}): void {
|
||||
if (!condition) throw new Error(`${message}: ${JSON.stringify(detail)}`);
|
||||
@@ -24,6 +24,13 @@ assertCondition(
|
||||
hwlabG14MonitorStateFileName({ once: true, dryRun: true }) === "latest-once-dry-run-job.json",
|
||||
"once dry-runs need a distinct pointer for low-noise diagnostics",
|
||||
);
|
||||
const hwlabHelpUsage = Array.isArray(hwlabG14Help().usage) ? hwlabG14Help().usage.map(String) : [];
|
||||
assertCondition(
|
||||
hwlabHelpUsage.some((line) => line.includes("control-plane status --lane v02 --pipeline-run"))
|
||||
&& hwlabHelpUsage.some((line) => line.includes("control-plane status --lane v02 --source-commit")),
|
||||
"v0.2 control-plane status help must expose targeted PipelineRun/source-commit inspection",
|
||||
hwlabHelpUsage,
|
||||
);
|
||||
|
||||
const gitMirrorJob = gitMirrorSyncJobManifest("git-mirror-hwlab-sync-manual-test");
|
||||
assertCondition(gitMirrorJob.kind === "Job", "git mirror sync must be a manual Job, not a CronJob", gitMirrorJob);
|
||||
@@ -316,6 +323,7 @@ console.log(JSON.stringify({
|
||||
"git mirror flush is a manual devops-infra Job, not a CronJob",
|
||||
"trigger-current can decide whether v0.2 git mirror pre-sync is required",
|
||||
"git mirror status exposes source and gitops GitHub sync state plus controlled flush command",
|
||||
"v0.2 control-plane status help exposes targeted PipelineRun/source-commit inspection",
|
||||
"v0.2 control-plane render uses a detached temp worktree from a CI/CD dedicated bare repo",
|
||||
"v0.2 status alignment reports stale-success without coupling CI to dirty workspace state",
|
||||
"v0.2 PipelineRun service matrix excludes hwlab-cli",
|
||||
|
||||
+90
-17
@@ -91,6 +91,16 @@ interface G14ControlPlaneOptions {
|
||||
timeoutSeconds: number;
|
||||
minAgeMinutes: number;
|
||||
limit: number;
|
||||
sourceCommit?: string;
|
||||
pipelineRun?: string;
|
||||
}
|
||||
|
||||
type V02StatusTargetMode = "latest-source-head" | "source-commit" | "pipeline-run";
|
||||
|
||||
interface V02ControlPlaneStatusTarget {
|
||||
sourceCommit?: string | null;
|
||||
pipelineRun?: string | null;
|
||||
mode?: V02StatusTargetMode;
|
||||
}
|
||||
|
||||
interface G14ToolsImageOptions {
|
||||
@@ -193,6 +203,16 @@ function optionValue(args: string[], name: string): string | undefined {
|
||||
return value;
|
||||
}
|
||||
|
||||
function validateFullShaOption(value: string, name: string): string {
|
||||
if (!/^[0-9a-f]{40}$/iu.test(value)) throw new Error(`${name} must be a full 40-character git SHA`);
|
||||
return value.toLowerCase();
|
||||
}
|
||||
|
||||
function validateV02PipelineRunOption(value: string): string {
|
||||
if (!/^hwlab-v02-ci-poll-[0-9a-f]{7,40}$/iu.test(value)) throw new Error("--pipeline-run must be a hwlab-v02-ci-poll-<sha> PipelineRun name");
|
||||
return value.toLowerCase();
|
||||
}
|
||||
|
||||
function parseRecordRolloutOptions(args: string[]): G14RecordRolloutOptions {
|
||||
const prRaw = optionValue(args, "--pr") ?? optionValue(args, "--number");
|
||||
const prNumber = Number(prRaw);
|
||||
@@ -236,6 +256,12 @@ function parseControlPlaneOptions(args: string[]): G14ControlPlaneOptions {
|
||||
const allowLiveDbRead = args.includes("--allow-live-db-read");
|
||||
if (allowLiveDbRead && confirm) throw new Error("control-plane runtime-migration accepts --allow-live-db-read only with dry-run/source-check mode, not --confirm");
|
||||
if (allowLiveDbRead && actionRaw !== "runtime-migration") throw new Error("--allow-live-db-read is only valid for control-plane runtime-migration");
|
||||
const sourceCommitRaw = optionValue(args, "--source-commit");
|
||||
const pipelineRunRaw = optionValue(args, "--pipeline-run");
|
||||
if ((sourceCommitRaw !== undefined || pipelineRunRaw !== undefined) && actionRaw !== "status") {
|
||||
throw new Error("--source-commit and --pipeline-run are only valid for control-plane status");
|
||||
}
|
||||
if (sourceCommitRaw !== undefined && pipelineRunRaw !== undefined) throw new Error("control-plane status accepts only one of --source-commit or --pipeline-run");
|
||||
return {
|
||||
action: actionRaw,
|
||||
lane,
|
||||
@@ -246,6 +272,8 @@ function parseControlPlaneOptions(args: string[]): G14ControlPlaneOptions {
|
||||
timeoutSeconds: positiveIntegerOption(args, "--timeout-seconds", 120, 600),
|
||||
minAgeMinutes: positiveIntegerOption(args, "--min-age-minutes", 60, 10080),
|
||||
limit: positiveIntegerOption(args, "--limit", 20, 200),
|
||||
sourceCommit: sourceCommitRaw === undefined ? undefined : validateFullShaOption(sourceCommitRaw, "--source-commit"),
|
||||
pipelineRun: pipelineRunRaw === undefined ? undefined : validateV02PipelineRunOption(pipelineRunRaw),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -717,15 +745,26 @@ function shellSectionOk(section: ShellSection | undefined): boolean {
|
||||
return section?.exitCode === 0;
|
||||
}
|
||||
|
||||
function v02ControlPlaneStatusBundle(sourceCommit: string | null | undefined): CommandJsonResult {
|
||||
const sourceCommitLine = sourceCommit === undefined
|
||||
? `source_commit=$(git --git-dir=${shellQuote(V02_CICD_REPO)} rev-parse refs/remotes/origin/v0.2 2>/dev/null || true)`
|
||||
: `source_commit=${shellQuote(sourceCommit ?? "")}`;
|
||||
function v02ControlPlaneStatusBundle(target: V02ControlPlaneStatusTarget = {}): CommandJsonResult {
|
||||
const targetMode: V02StatusTargetMode = target.mode
|
||||
?? (target.pipelineRun !== undefined && target.pipelineRun !== null ? "pipeline-run" : target.sourceCommit !== undefined ? "source-commit" : "latest-source-head");
|
||||
const targetInit = target.pipelineRun !== undefined && target.pipelineRun !== null
|
||||
? [
|
||||
`pipeline_run=${shellQuote(target.pipelineRun)}`,
|
||||
`source_commit=$(kubectl get pipelinerun -n ${shellQuote(CI_NAMESPACE)} "$pipeline_run" -o 'jsonpath={.metadata.labels.hwlab\\.pikastech\\.local/source-commit}' 2>/dev/null || true)`,
|
||||
`if [ -z "$source_commit" ]; then source_commit=$(printf '%s' "$pipeline_run" | cut -d- -f5-); fi`,
|
||||
].join("\n")
|
||||
: [
|
||||
target.sourceCommit === undefined
|
||||
? `source_commit=$(git --git-dir=${shellQuote(V02_CICD_REPO)} rev-parse refs/remotes/origin/v0.2 2>/dev/null || true)`
|
||||
: `source_commit=${shellQuote(target.sourceCommit ?? "")}`,
|
||||
"pipeline_run=",
|
||||
].join("\n");
|
||||
const script = [
|
||||
"set +e",
|
||||
sourceCommitLine,
|
||||
"pipeline_run=",
|
||||
`if [ -n "$source_commit" ]; then pipeline_run="${V02_PIPELINERUN_PREFIX}-$(printf '%s' "$source_commit" | cut -c1-12)"; fi`,
|
||||
targetInit,
|
||||
`target_mode=${shellQuote(targetMode)}`,
|
||||
`if [ -z "$pipeline_run" ] && [ -n "$source_commit" ]; then pipeline_run="${V02_PIPELINERUN_PREFIX}-$(printf '%s' "$source_commit" | cut -c1-12)"; fi`,
|
||||
"section() {",
|
||||
" name=\"$1\"",
|
||||
" shift",
|
||||
@@ -734,7 +773,9 @@ function v02ControlPlaneStatusBundle(sourceCommit: string | null | undefined): C
|
||||
" code=$?",
|
||||
" printf '\\n__UNIDESK_SECTION_END__ %s exit=%s\\n' \"$name\" \"$code\"",
|
||||
"}",
|
||||
"section statusTarget printf 'mode\\t%s\\nsourceCommit\\t%s\\npipelineRun\\t%s\\n' \"$target_mode\" \"$source_commit\" \"$pipeline_run\"",
|
||||
"section sourceCommit printf '%s\\n' \"$source_commit\"",
|
||||
"section pipelineRunName printf '%s\\n' \"$pipeline_run\"",
|
||||
`section sourceHeads sh -c ${shellQuote(v02SourceHeadsProbeScript())}`,
|
||||
"section queryNow date -u +%Y-%m-%dT%H:%M:%SZ",
|
||||
`section controlPlane kubectl get pipeline,role,rolebinding,serviceaccount -n ${shellQuote(CI_NAMESPACE)} -l hwlab.pikastech.local/gitops-target=v02 -o name`,
|
||||
@@ -1805,11 +1846,15 @@ function deleteV02PipelineRun(pipelineRun: string): CommandJsonResult {
|
||||
return g14K3s(["kubectl", "delete", "pipelinerun", "-n", CI_NAMESPACE, pipelineRun, "--ignore-not-found=true"], 60_000);
|
||||
}
|
||||
|
||||
function v02ControlPlaneStatus(sourceCommitInput?: string | null): Record<string, unknown> {
|
||||
const bundle = v02ControlPlaneStatusBundle(sourceCommitInput);
|
||||
function v02ControlPlaneStatus(target: V02ControlPlaneStatusTarget = {}): Record<string, unknown> {
|
||||
const targetMode: V02StatusTargetMode = target.mode
|
||||
?? (target.pipelineRun !== undefined && target.pipelineRun !== null ? "pipeline-run" : target.sourceCommit !== undefined ? "source-commit" : "latest-source-head");
|
||||
const strictHeadAlignment = targetMode === "latest-source-head";
|
||||
const bundle = v02ControlPlaneStatusBundle({ ...target, mode: targetMode });
|
||||
const sections = parseShellSections(statusText(bundle));
|
||||
const sourceCommit = stringOrNull(sections.sourceCommit?.stdout) ?? null;
|
||||
const pipelineRun = sourceCommit === null ? null : v02PipelineRunName(sourceCommit);
|
||||
const pipelineRun = stringOrNull(sections.pipelineRunName?.stdout) ?? (sourceCommit === null ? null : v02PipelineRunName(sourceCommit));
|
||||
const statusTargetFields = keyValueLinesFromText(sections.statusTarget?.stdout ?? "");
|
||||
const queryNowMs = timestampMs(sections.queryNow?.stdout) ?? Date.now();
|
||||
const sourceHeadsSection = sections.sourceHeads;
|
||||
const controlPlane = sections.controlPlane;
|
||||
@@ -1895,14 +1940,38 @@ function v02ControlPlaneStatus(sourceCommitInput?: string | null): Record<string
|
||||
webAssets,
|
||||
});
|
||||
const baseOk = sourceCommit !== null && isCommandSuccess(bundle) && shellSectionOk(controlPlane) && shellSectionOk(argo);
|
||||
const targetPipelineRunOk = strictHeadAlignment
|
||||
? true
|
||||
: pipelineRunInfo !== null && pipelineRunInfo.ok === true && pipelineRunInfo.exists !== false;
|
||||
const targetDegradedReason = !strictHeadAlignment && !targetPipelineRunOk ? "target-pipelinerun-not-found-or-unreadable" : undefined;
|
||||
const statusCommand = targetMode === "pipeline-run" && pipelineRun !== null
|
||||
? `hwlab g14 control-plane status --lane v02 --pipeline-run ${pipelineRun}`
|
||||
: targetMode === "source-commit" && sourceCommit !== null
|
||||
? `hwlab g14 control-plane status --lane v02 --source-commit ${sourceCommit}`
|
||||
: "hwlab g14 control-plane status --lane v02";
|
||||
const state = strictHeadAlignment ? commitAlignment.state : `target-${targetMode}`;
|
||||
const sourceCommitSource = targetMode === "pipeline-run"
|
||||
? "PipelineRun metadata label hwlab.pikastech.local/source-commit"
|
||||
: targetMode === "source-commit"
|
||||
? "explicit --source-commit"
|
||||
: "G14 CI/CD dedicated bare repo refs/remotes/origin/v0.2; workspace checkout is observable but isolated";
|
||||
return {
|
||||
ok: baseOk && commitAlignment.aligned !== false,
|
||||
command: "hwlab g14 control-plane status --lane v02",
|
||||
ok: baseOk && targetPipelineRunOk && (!strictHeadAlignment || commitAlignment.aligned !== false),
|
||||
command: statusCommand,
|
||||
lane: "v02",
|
||||
state: commitAlignment.state,
|
||||
degradedReason: commitAlignment.aligned === false ? commitAlignment.state : undefined,
|
||||
state,
|
||||
degradedReason: strictHeadAlignment && commitAlignment.aligned === false ? commitAlignment.state : targetDegradedReason,
|
||||
statusTarget: {
|
||||
mode: statusTargetFields.mode || targetMode,
|
||||
sourceCommit,
|
||||
pipelineRun,
|
||||
strictHeadAlignment,
|
||||
note: strictHeadAlignment
|
||||
? "default status validates the latest v0.2 source head alignment"
|
||||
: "targeted status inspects the requested PipelineRun/source commit without failing merely because origin/v0.2 advanced later",
|
||||
},
|
||||
sourceCommit,
|
||||
sourceCommitSource: "G14 CI/CD dedicated bare repo refs/remotes/origin/v0.2; workspace checkout is observable but isolated",
|
||||
sourceCommitSource,
|
||||
expected: {
|
||||
sourceRepo: V02_CICD_REPO,
|
||||
workspace: V02_WORKSPACE,
|
||||
@@ -1956,12 +2025,14 @@ function v02ControlPlaneStatus(sourceCommitInput?: string | null): Record<string
|
||||
function runV02ControlPlane(options: G14ControlPlaneOptions): Record<string, unknown> {
|
||||
if (options.action === "cleanup-runs") return runControlPlaneCleanup(options);
|
||||
if (options.action === "cleanup-released-pvs") return runControlPlaneReleasedPvCleanup(options);
|
||||
if (options.action === "status" && options.pipelineRun !== undefined) return v02ControlPlaneStatus({ pipelineRun: options.pipelineRun, mode: "pipeline-run" });
|
||||
if (options.action === "status" && options.sourceCommit !== undefined) return v02ControlPlaneStatus({ sourceCommit: options.sourceCommit, mode: "source-commit" });
|
||||
const sourceCommit = getV02Head();
|
||||
if (sourceCommit === null) {
|
||||
return { ok: false, command: `hwlab g14 control-plane ${options.action} --lane v02`, degradedReason: "v02-head-unresolved", sourceRepo: V02_CICD_REPO, workspace: V02_WORKSPACE };
|
||||
}
|
||||
if (options.action === "runtime-migration") return runV02RuntimeMigration(options, sourceCommit);
|
||||
if (options.action === "status") return v02ControlPlaneStatus(sourceCommit);
|
||||
if (options.action === "status") return v02ControlPlaneStatus({ sourceCommit, mode: "latest-source-head" });
|
||||
if (options.action === "apply") {
|
||||
const render = runV02RenderToTemp(sourceCommit);
|
||||
if (!isCommandSuccess(render)) {
|
||||
@@ -1984,7 +2055,7 @@ function runV02ControlPlane(options: G14ControlPlaneOptions): Record<string, unk
|
||||
render: commandData(render),
|
||||
apply: compactCommandResult(apply),
|
||||
cleanupObsoleteCronJobs: compactCommandResult(options.dryRun ? deleteV02ObsoleteCronJobs(true) : deleteV02ObsoleteCronJobs(false)),
|
||||
status: v02ControlPlaneStatus(sourceCommit),
|
||||
status: v02ControlPlaneStatus({ sourceCommit, mode: "latest-source-head" }),
|
||||
next: options.dryRun
|
||||
? { apply: "bun scripts/cli.ts hwlab g14 control-plane apply --lane v02 --confirm" }
|
||||
: { triggerCurrent: "bun scripts/cli.ts hwlab g14 control-plane trigger-current --lane v02 --confirm" },
|
||||
@@ -3588,6 +3659,8 @@ export function hwlabG14Help(): Record<string, unknown> {
|
||||
"bun scripts/cli.ts hwlab g14 monitor-prs --once --dry-run",
|
||||
"bun scripts/cli.ts hwlab g14 record-rollout --pr <number> [--source-commit sha]",
|
||||
"bun scripts/cli.ts hwlab g14 control-plane status --lane v02",
|
||||
"bun scripts/cli.ts hwlab g14 control-plane status --lane v02 --pipeline-run hwlab-v02-ci-poll-<short-sha>",
|
||||
"bun scripts/cli.ts hwlab g14 control-plane status --lane v02 --source-commit <full-sha>",
|
||||
"bun scripts/cli.ts hwlab g14 control-plane apply --lane v02 --dry-run",
|
||||
"bun scripts/cli.ts hwlab g14 control-plane apply --lane v02 --confirm",
|
||||
"bun scripts/cli.ts hwlab g14 control-plane trigger-current --lane v02 --confirm",
|
||||
|
||||
Reference in New Issue
Block a user