fix: 修复部署观测提交匹配假阴性
This commit is contained in:
parent
e559e0ee55
commit
1c768c1e79
@ -19,7 +19,7 @@
|
|||||||
- 生成改动文档同步计划:按变更文件自动提示需要同步的 README、API、AGENTS、docs、Obsidian、skill 和 ktWorkflow 入口。
|
- 生成改动文档同步计划:按变更文件自动提示需要同步的 README、API、AGENTS、docs、Obsidian、skill 和 ktWorkflow 入口。
|
||||||
- 生成多仓库提交/推送计划:按仓库分组、建议提交信息、列出提交和推送前检查。
|
- 生成多仓库提交/推送计划:按仓库分组、建议提交信息、列出提交和推送前检查。
|
||||||
- 生成远程只读健康检查和数据库同步安全向导:覆盖飞牛 NAS 服务探测、GTID、`.kt-workspace/db-sync` 转储、备份库和行数校验。
|
- 生成远程只读健康检查和数据库同步安全向导:覆盖飞牛 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 的防踩坑清单和验证点。
|
- 生成专项组件工作流:KtTable、BlogArgon、AdminAuth、QQBot、FF14Plugin、NapCatLogin、SystemLog、Knife4jSwagger、FnosK8s 的防踩坑清单和验证点。
|
||||||
- 生成验证进程清理计划:按项目路径和端口给出 PowerShell 检查命令,不直接杀进程。
|
- 生成验证进程清理计划:按项目路径和端口给出 PowerShell 检查命令,不直接杀进程。
|
||||||
- 清理历史产物:统一治理 `.kt-workspace` 下的测试/验证产物,按目录最近修改时间只保留最近 3 轮,模板目录永久保留;CLI 默认 dry-run,真实清理必须显式传 `--execute`。
|
- 清理历史产物:统一治理 `.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_business_test_plan` | 生成固化业务链路测试计划,包含 QQBot SSE、FFLogs 和系统日志 |
|
||||||
| `kt_blocker_resolution` | 生成或写入卡点固化记录,提醒停止原样重试 |
|
| `kt_blocker_resolution` | 生成或写入卡点固化记录,提醒停止原样重试 |
|
||||||
| `kt_remote_health_check` | 生成或执行远程只读健康检查命令 |
|
| `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_db_sync_plan` | 生成数据库同步安全向导 |
|
||||||
| `kt_component_workflow` | 输出专项组件/链路防踩坑工作流,包含 FnosK8s |
|
| `kt_component_workflow` | 输出专项组件/链路防踩坑工作流,包含 FnosK8s |
|
||||||
| `kt_obsidian_context` | 读取 Obsidian 索引上下文,支持按 `module` / `query` 返回模块页、文档矩阵、Canvas 摘要、代码锚点和相关规则文档 |
|
| `kt_obsidian_context` | 读取 Obsidian 索引上下文,支持按 `module` / `query` 返回模块页、文档矩阵、Canvas 摘要、代码锚点和相关规则文档 |
|
||||||
|
|||||||
@ -398,6 +398,8 @@ export async function runSelfTest(): Promise<void> {
|
|||||||
const buildDeployObservationTestSections = (overrides: {
|
const buildDeployObservationTestSections = (overrides: {
|
||||||
desiredReplicas?: number;
|
desiredReplicas?: number;
|
||||||
healthStatus?: string;
|
healthStatus?: string;
|
||||||
|
jenkinsBuildXml?: string;
|
||||||
|
logCommit?: string;
|
||||||
omitSmoke?: boolean;
|
omitSmoke?: boolean;
|
||||||
readyReplicas?: number;
|
readyReplicas?: number;
|
||||||
smokeExitCode?: number;
|
smokeExitCode?: number;
|
||||||
@ -410,8 +412,12 @@ export async function runSelfTest(): Promise<void> {
|
|||||||
"buildNumber=132",
|
"buildNumber=132",
|
||||||
"result=SUCCESS",
|
"result=SUCCESS",
|
||||||
"__KT_SECTION:jenkins_log_tail__",
|
"__KT_SECTION:jenkins_log_tail__",
|
||||||
"Checking out Revision abc1234",
|
overrides.logCommit === ""
|
||||||
|
? "Finished: SUCCESS"
|
||||||
|
: `Checking out Revision ${overrides.logCommit ?? "abc1234"}`,
|
||||||
"Finished: SUCCESS",
|
"Finished: SUCCESS",
|
||||||
|
"__KT_SECTION:jenkins_build_xml__",
|
||||||
|
overrides.jenkinsBuildXml ?? "",
|
||||||
"__KT_SECTION:deployment_json__",
|
"__KT_SECTION:deployment_json__",
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
metadata: { generation: 12 },
|
metadata: { generation: 12 },
|
||||||
@ -531,6 +537,28 @@ export async function runSelfTest(): Promise<void> {
|
|||||||
throw new Error("deploy observation degraded health self-check failed");
|
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 =
|
const deployObservationFailedSmokeEvidence =
|
||||||
normalizeDeployObservationEvidence({
|
normalizeDeployObservationEvidence({
|
||||||
checkedAt: new Date("2026-06-14T00:00:02.000Z"),
|
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}",
|
"127.0.0.1:${K3D_API_PORT}",
|
||||||
'rm -f "$KUBECONFIG_TEMP"',
|
'rm -f "$KUBECONFIG_TEMP"',
|
||||||
'kubectl --kubeconfig "$KUBECONFIG_ACTIVE"',
|
'kubectl --kubeconfig "$KUBECONFIG_ACTIVE"',
|
||||||
|
"section jenkins_build_xml",
|
||||||
]) {
|
]) {
|
||||||
if (!deployObservationCommandText.includes(expected)) {
|
if (!deployObservationCommandText.includes(expected)) {
|
||||||
throw new Error(`deploy observation kubeconfig self-check failed: ${expected}`);
|
throw new Error(`deploy observation kubeconfig self-check failed: ${expected}`);
|
||||||
|
|||||||
@ -332,6 +332,8 @@ function buildRemoteScript(input: NormalizedInput): string {
|
|||||||
'printf "buildNumber=%s\\n" "$BUILD_NUMBER"',
|
'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',
|
'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"',
|
'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',
|
'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',
|
'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',
|
'section deployment_json',
|
||||||
@ -400,6 +402,8 @@ function normalizeJenkinsEvidence(
|
|||||||
): DeployObservationJenkinsEvidence {
|
): DeployObservationJenkinsEvidence {
|
||||||
const meta = readKeyValueSection(sectionMap.get('jenkins_meta') || '');
|
const meta = readKeyValueSection(sectionMap.get('jenkins_meta') || '');
|
||||||
const logTail = sectionMap.get('jenkins_log_tail') || '';
|
const logTail = sectionMap.get('jenkins_log_tail') || '';
|
||||||
|
const buildXmlRevision = sectionMap.get('jenkins_build_xml') || '';
|
||||||
|
const commitHaystack = `${logTail}\n${buildXmlRevision}`.toLowerCase();
|
||||||
const finishedStatus =
|
const finishedStatus =
|
||||||
meta.result ||
|
meta.result ||
|
||||||
logTail.match(/Finished:\s*([A-Z_]+)/i)?.[1]?.toUpperCase() ||
|
logTail.match(/Finished:\s*([A-Z_]+)/i)?.[1]?.toUpperCase() ||
|
||||||
@ -409,7 +413,7 @@ function normalizeJenkinsEvidence(
|
|||||||
return {
|
return {
|
||||||
buildNumber: meta.buildNumber || input.buildNumber || null,
|
buildNumber: meta.buildNumber || input.buildNumber || null,
|
||||||
commitMatched: expectedCommit
|
commitMatched: expectedCommit
|
||||||
? logTail.toLowerCase().includes(expectedCommit.toLowerCase())
|
? commitHaystack.includes(expectedCommit.toLowerCase())
|
||||||
: null,
|
: null,
|
||||||
expectedCommit,
|
expectedCommit,
|
||||||
finishedStatus,
|
finishedStatus,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user