feat: 增加NapCat镜像漂移审查
This commit is contained in:
parent
64da1ebc03
commit
aebd0a67fd
@ -23,7 +23,7 @@
|
|||||||
- 生成验证进程清理计划:按项目路径和端口给出 PowerShell 检查命令,不直接杀进程。
|
- 生成验证进程清理计划:按项目路径和端口给出 PowerShell 检查命令,不直接杀进程。
|
||||||
- 清理历史产物:统一治理 `.kt-workspace` 下的测试/验证产物,按目录最近修改时间只保留最近 3 轮,模板目录永久保留;CLI 默认 dry-run,真实清理必须显式传 `--execute`。
|
- 清理历史产物:统一治理 `.kt-workspace` 下的测试/验证产物,按目录最近修改时间只保留最近 3 轮,模板目录永久保留;CLI 默认 dry-run,真实清理必须显式传 `--execute`。
|
||||||
- 检查 env 策略和变更风险:区分后端真实 env 与前端客户端 `.env*`,提醒锁文件、核心表格组件、部署链路和 Vue TSX 插槽写法等高风险改动。
|
- 检查 env 策略和变更风险:区分后端真实 env 与前端客户端 `.env*`,提醒锁文件、核心表格组件、部署链路和 Vue TSX 插槽写法等高风险改动。
|
||||||
- 全局 CodeReview 只读扫描:汇总全部 KT 子仓库的 Git 状态、敏感文件跟踪、冲突标记、运行时调试输出、疑似凭据字面量、根目录生成产物、`TASKS.md` 最近记录字段结构和当前变更风险;默认只对变更文件做内容扫描,并放过短中文显示标签,避免历史误报污染上下文;任何文件改动后都要跑一遍。
|
- 全局 CodeReview 只读扫描:汇总全部 KT 子仓库的 Git 状态、敏感文件跟踪、冲突标记、运行时调试输出、疑似凭据字面量、NapCat `latest` 镜像漂移风险、根目录生成产物、`TASKS.md` 最近记录字段结构和当前变更风险;默认只对变更文件做内容扫描,并放过短中文显示标签,避免历史误报污染上下文;任何文件改动后都要跑一遍。
|
||||||
- 生成或写入 `TASKS.md` 最近记录:默认 `dryRun=true`,确认后再落盘。
|
- 生成或写入 `TASKS.md` 最近记录:默认 `dryRun=true`,确认后再落盘。
|
||||||
- 生成提交前检查清单:校验 KT commit message 约定。
|
- 生成提交前检查清单:校验 KT commit message 约定。
|
||||||
|
|
||||||
|
|||||||
@ -12,7 +12,7 @@ import { cleanupHistoryArtifacts, parseCliCleanupArgs } from './tools/cleanup.js
|
|||||||
import { buildWorkflowLoopAudit } from './tools/loop.js';
|
import { buildWorkflowLoopAudit } from './tools/loop.js';
|
||||||
import { inspectProject } from './tools/inspect.js';
|
import { inspectProject } from './tools/inspect.js';
|
||||||
import { prepareTask, readWorkflowContext } from './tools/task.js';
|
import { prepareTask, readWorkflowContext } from './tools/task.js';
|
||||||
import { buildGlobalCodeReview, findTaskRecordGovernanceFindings, isBenignCredentialReviewValue } from './tools/review.js';
|
import { buildGlobalCodeReview, findNapcatImageGovernanceFindings, findTaskRecordGovernanceFindings, isBenignCredentialReviewValue } from './tools/review.js';
|
||||||
import { buildBusinessTestPlan } from './tools/testing.js';
|
import { buildBusinessTestPlan } from './tools/testing.js';
|
||||||
import { buildVerificationPlan } from './tools/verification.js';
|
import { buildVerificationPlan } from './tools/verification.js';
|
||||||
import { buildWorkstreamCloseout } from './tools/closeout.js';
|
import { buildWorkstreamCloseout } from './tools/closeout.js';
|
||||||
@ -39,6 +39,17 @@ export async function runSelfTest(): Promise<void> {
|
|||||||
throw new Error('TASKS record governance self-check failed');
|
throw new Error('TASKS record governance self-check failed');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const napcatImageFindings = findNapcatImageGovernanceFindings(
|
||||||
|
['QQBOT_NAPCAT_IMAGE=mlikiowa/napcat-docker:latest'],
|
||||||
|
{
|
||||||
|
file: '.env.example',
|
||||||
|
project: 'Node/kt-template-online-api',
|
||||||
|
},
|
||||||
|
);
|
||||||
|
if (!napcatImageFindings.some((item) => item.category === 'napcat-latest-image')) {
|
||||||
|
throw new Error('NapCat image governance self-check failed');
|
||||||
|
}
|
||||||
|
|
||||||
const reviewCliParser = {
|
const reviewCliParser = {
|
||||||
dashedAll: parseGlobalReviewCliArgs(['node', 'server', '--global-review', '--content-scan-all']).contentScanMode,
|
dashedAll: parseGlobalReviewCliArgs(['node', 'server', '--global-review', '--content-scan-all']).contentScanMode,
|
||||||
keyValueAll: parseGlobalReviewCliArgs(['node', 'server', '--global-review', '--contentScanMode=all']).contentScanMode,
|
keyValueAll: parseGlobalReviewCliArgs(['node', 'server', '--global-review', '--contentScanMode=all']).contentScanMode,
|
||||||
|
|||||||
@ -54,6 +54,8 @@ const frontendEnvProjectAliases = new Set<ProjectAlias>([
|
|||||||
|
|
||||||
const credentialAssignmentPattern =
|
const credentialAssignmentPattern =
|
||||||
/\b(password|passwd|secret|token|webuiToken|accessToken|privateKey)\b\s*[:=]\s*(["'])([^"']+)\2/i;
|
/\b(password|passwd|secret|token|webuiToken|accessToken|privateKey)\b\s*[:=]\s*(["'])([^"']+)\2/i;
|
||||||
|
const napcatImageAssignmentPattern =
|
||||||
|
/^\s*QQBOT_NAPCAT_IMAGE\s*=\s*([^#\s]+)\s*(?:#.*)?$/;
|
||||||
const taskRecordAllowedFields = new Set(['范围', '关键词', '验证']);
|
const taskRecordAllowedFields = new Set(['范围', '关键词', '验证']);
|
||||||
const taskRecordRequiredFields = ['范围', '关键词', '验证'] as const;
|
const taskRecordRequiredFields = ['范围', '关键词', '验证'] as const;
|
||||||
|
|
||||||
@ -153,6 +155,37 @@ export function findTaskRecordGovernanceFindings(lines: string[]): ReviewFinding
|
|||||||
return findings;
|
return findings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function findNapcatImageGovernanceFindings(
|
||||||
|
lines: string[],
|
||||||
|
context: {
|
||||||
|
file: string;
|
||||||
|
project: string;
|
||||||
|
},
|
||||||
|
): ReviewFinding[] {
|
||||||
|
return lines.flatMap((line, index) => {
|
||||||
|
const trimmed = line.trim();
|
||||||
|
if (!trimmed || trimmed.startsWith('#')) return [];
|
||||||
|
|
||||||
|
const matched = line.match(napcatImageAssignmentPattern);
|
||||||
|
if (!matched) return [];
|
||||||
|
|
||||||
|
const image = matched[1].trim();
|
||||||
|
if (!image.endsWith(':latest')) return [];
|
||||||
|
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
category: 'napcat-latest-image',
|
||||||
|
file: context.file,
|
||||||
|
line: index + 1,
|
||||||
|
level: 'P3' as const,
|
||||||
|
message: 'NapCat 运行镜像使用 latest,生产排查会受到镜像漂移影响。',
|
||||||
|
project: context.project,
|
||||||
|
suggestion: '改为明确版本 tag 或 digest,并先在单账号容器观察稳定性后推广。',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
async function listGitTrackedFiles(projectPath: string): Promise<string[]> {
|
async function listGitTrackedFiles(projectPath: string): Promise<string[]> {
|
||||||
const tracked = await tryExecFile('git', ['ls-files'], projectPath);
|
const tracked = await tryExecFile('git', ['ls-files'], projectPath);
|
||||||
if (!tracked.ok) return [];
|
if (!tracked.ok) return [];
|
||||||
@ -324,6 +357,15 @@ function collectProjectContentFindings(
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (includeContentScan) {
|
||||||
|
findings.push(
|
||||||
|
...findNapcatImageGovernanceFindings(lines, {
|
||||||
|
file,
|
||||||
|
project: project.relativePath,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
findings.length + credentialHints.length + debugFindings.length >=
|
findings.length + credentialHints.length + debugFindings.length >=
|
||||||
maxFindings * 3
|
maxFindings * 3
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user