fix: 修复部署观测提交匹配假阴性

This commit is contained in:
sunlei 2026-06-14 23:08:18 +08:00
parent e559e0ee55
commit 1c768c1e79
3 changed files with 37 additions and 4 deletions

View File

@ -19,7 +19,7 @@
- 生成改动文档同步计划:按变更文件自动提示需要同步的 README、API、AGENTS、docs、Obsidian、skill 和 ktWorkflow 入口。
- 生成多仓库提交/推送计划:按仓库分组、建议提交信息、列出提交和推送前检查。
- 生成远程只读健康检查和数据库同步安全向导:覆盖飞牛 NAS 服务探测、GTID、`.kt-workspace/db-sync` 转储、备份库和行数校验。
- 生成或执行部署观测:把 Jenkins build、commit、K8s Deployment、Pod、`/health/runtime` 和任务 smoke 汇总成 `.kt-workspace/test-artifacts/deploy-observation` 下的运行态证据。
- 生成或执行部署观测:把 Jenkins build、`build.xml` SCM revision、日志尾部、K8s Deployment、Pod、`/health/runtime` 和任务 smoke 汇总成 `.kt-workspace/test-artifacts/deploy-observation` 下的运行态证据。
- 生成专项组件工作流KtTable、BlogArgon、AdminAuth、QQBot、FF14Plugin、NapCatLogin、SystemLog、Knife4jSwagger、FnosK8s 的防踩坑清单和验证点。
- 生成验证进程清理计划:按项目路径和端口给出 PowerShell 检查命令,不直接杀进程。
- 清理历史产物:统一治理 `.kt-workspace` 下的测试/验证产物,按目录最近修改时间只保留最近 3 轮模板目录永久保留CLI 默认 dry-run真实清理必须显式传 `--execute`
@ -95,7 +95,7 @@ pnpm run admin-login -- --url http://127.0.0.1:5999/#/auth/login
| `kt_business_test_plan` | 生成固化业务链路测试计划,包含 QQBot SSE、FFLogs 和系统日志 |
| `kt_blocker_resolution` | 生成或写入卡点固化记录,提醒停止原样重试 |
| `kt_remote_health_check` | 生成或执行远程只读健康检查命令 |
| `kt_deploy_observation` | 生成或执行 API 发布后的部署观测,汇总 Jenkins、K8s、Pod、`/health/runtime` 和任务 smoke 证据 |
| `kt_deploy_observation` | 生成或执行 API 发布后的部署观测,汇总 Jenkins SCM revision、K8s、Pod、`/health/runtime` 和任务 smoke 证据 |
| `kt_db_sync_plan` | 生成数据库同步安全向导 |
| `kt_component_workflow` | 输出专项组件/链路防踩坑工作流,包含 FnosK8s |
| `kt_obsidian_context` | 读取 Obsidian 索引上下文,支持按 `module` / `query` 返回模块页、文档矩阵、Canvas 摘要、代码锚点和相关规则文档 |

View File

@ -398,6 +398,8 @@ export async function runSelfTest(): Promise<void> {
const buildDeployObservationTestSections = (overrides: {
desiredReplicas?: number;
healthStatus?: string;
jenkinsBuildXml?: string;
logCommit?: string;
omitSmoke?: boolean;
readyReplicas?: number;
smokeExitCode?: number;
@ -410,8 +412,12 @@ export async function runSelfTest(): Promise<void> {
"buildNumber=132",
"result=SUCCESS",
"__KT_SECTION:jenkins_log_tail__",
"Checking out Revision abc1234",
overrides.logCommit === ""
? "Finished: SUCCESS"
: `Checking out Revision ${overrides.logCommit ?? "abc1234"}`,
"Finished: SUCCESS",
"__KT_SECTION:jenkins_build_xml__",
overrides.jenkinsBuildXml ?? "",
"__KT_SECTION:deployment_json__",
JSON.stringify({
metadata: { generation: 12 },
@ -531,6 +537,28 @@ export async function runSelfTest(): Promise<void> {
throw new Error("deploy observation degraded health self-check failed");
}
const deployObservationBuildXmlCommitEvidence =
normalizeDeployObservationEvidence({
checkedAt: new Date("2026-06-14T00:00:02.000Z"),
input: deployObservationInput,
sectionMap: buildDeployObservationTestSections({
jenkinsBuildXml: [
"<jenkins.scm.api.SCMRevisionAction>",
"<revision>",
"<hash>abc1234</hash>",
"</revision>",
"</jenkins.scm.api.SCMRevisionAction>",
].join("\n"),
logCommit: "",
}),
});
if (
deployObservationBuildXmlCommitEvidence.status !== "passed" ||
deployObservationBuildXmlCommitEvidence.details.jenkins.commitMatched !== true
) {
throw new Error("deploy observation build.xml commit self-check failed");
}
const deployObservationFailedSmokeEvidence =
normalizeDeployObservationEvidence({
checkedAt: new Date("2026-06-14T00:00:02.000Z"),
@ -644,6 +672,7 @@ export async function runSelfTest(): Promise<void> {
"127.0.0.1:${K3D_API_PORT}",
'rm -f "$KUBECONFIG_TEMP"',
'kubectl --kubeconfig "$KUBECONFIG_ACTIVE"',
"section jenkins_build_xml",
]) {
if (!deployObservationCommandText.includes(expected)) {
throw new Error(`deploy observation kubeconfig self-check failed: ${expected}`);

View File

@ -332,6 +332,8 @@ function buildRemoteScript(input: NormalizedInput): string {
'printf "buildNumber=%s\\n" "$BUILD_NUMBER"',
'if [ -f "$BUILD_DIR/build.xml" ]; then RESULT="$(grep -Eo "<result>[^<]*</result>" "$BUILD_DIR/build.xml" 2>/dev/null | sed -E "s#</?result>##g" | tail -1 || true)"; else RESULT=""; fi',
'printf "result=%s\\n" "$RESULT"',
'section jenkins_build_xml',
'if [ -f "$BUILD_DIR/build.xml" ]; then grep -E "<(hash|sha1)>[0-9a-fA-F]{7,40}</(hash|sha1)>" "$BUILD_DIR/build.xml" 2>/dev/null | head -n 20 || true; else echo "jenkins build.xml not found: $BUILD_DIR/build.xml"; fi',
'section jenkins_log_tail',
'if [ -f "$BUILD_DIR/log" ]; then tail -n 160 "$BUILD_DIR/log"; else echo "jenkins log not found: $BUILD_DIR/log"; fi',
'section deployment_json',
@ -400,6 +402,8 @@ function normalizeJenkinsEvidence(
): DeployObservationJenkinsEvidence {
const meta = readKeyValueSection(sectionMap.get('jenkins_meta') || '');
const logTail = sectionMap.get('jenkins_log_tail') || '';
const buildXmlRevision = sectionMap.get('jenkins_build_xml') || '';
const commitHaystack = `${logTail}\n${buildXmlRevision}`.toLowerCase();
const finishedStatus =
meta.result ||
logTail.match(/Finished:\s*([A-Z_]+)/i)?.[1]?.toUpperCase() ||
@ -409,7 +413,7 @@ function normalizeJenkinsEvidence(
return {
buildNumber: meta.buildNumber || input.buildNumber || null,
commitMatched: expectedCommit
? logTail.toLowerCase().includes(expectedCommit.toLowerCase())
? commitHaystack.includes(expectedCommit.toLowerCase())
: null,
expectedCommit,
finishedStatus,