test: 加固NapCat上游审计Jenkins门禁

This commit is contained in:
sunlei 2026-06-25 04:03:21 +08:00
parent f9ce9b6015
commit 1abfcbf59d

View File

@ -470,29 +470,70 @@ export async function runSelfTest(): Promise<void> {
throw new Error(`NapCat upstream Jenkins template missing: ${expected}`);
}
}
const defaultUpstreamAuditIndex = upstreamSyncJenkinsTemplate.indexOf(
"run napcat-upstream-audit --",
);
const firstUpstreamExecuteIndex =
upstreamSyncJenkinsTemplate.indexOf("--execute");
if (
defaultUpstreamAuditIndex === -1 ||
(firstUpstreamExecuteIndex !== -1 &&
defaultUpstreamAuditIndex > firstUpstreamExecuteIndex)
) {
throw new Error(
"NapCat upstream Jenkins template must run dry-run audit before execute",
/**
* Verifies that the default upstream audit Jenkins call stays dry-run before the optional Codex execution stage.
* @param template - Full Jenkinsfile text to inspect.
* @returns Nothing; throws when the default audit call is unsafe.
*/
const assertUpstreamJenkinsDefaultAuditDryRun = (template: string): void => {
const defaultStageStart = template.indexOf(
"stage('ktWorkflow upstream audit dry-run')",
);
const codexStageStart = template.indexOf(
"stage('ktWorkflow upstream audit with Codex')",
);
if (
defaultStageStart === -1 ||
codexStageStart === -1 ||
defaultStageStart >= codexStageStart
) {
throw new Error(
"NapCat upstream Jenkins template default audit stage order self-check failed",
);
}
const defaultUpstreamAuditStage = template.slice(
defaultStageStart,
codexStageStart,
);
if (!defaultUpstreamAuditStage.includes("run napcat-upstream-audit --")) {
throw new Error(
"NapCat upstream Jenkins template default audit stage missing audit command",
);
}
for (const forbiddenFlag of ["--execute", "--use-codex"]) {
if (defaultUpstreamAuditStage.includes(forbiddenFlag)) {
throw new Error(
`NapCat upstream Jenkins template default audit must not include ${forbiddenFlag}`,
);
}
}
};
assertUpstreamJenkinsDefaultAuditDryRun(upstreamSyncJenkinsTemplate);
const unsafeDefaultUpstreamAuditTemplate = [
"stage('ktWorkflow upstream audit dry-run') {",
" pnpm --dir \"$KT_WORKFLOW_DIR\" run napcat-upstream-audit -- \\",
" --execute \\",
" --use-codex",
"}",
"stage('ktWorkflow upstream audit with Codex') {",
" pnpm --dir \"$KT_WORKFLOW_DIR\" run napcat-upstream-audit -- \\",
" --execute \\",
" --use-codex",
"}",
].join("\n");
let unsafeDefaultUpstreamAuditRejected = false;
try {
assertUpstreamJenkinsDefaultAuditDryRun(
unsafeDefaultUpstreamAuditTemplate,
);
} catch (error) {
unsafeDefaultUpstreamAuditRejected = String(error).includes(
"NapCat upstream Jenkins template default audit must not include",
);
}
const defaultUpstreamAuditCall = upstreamSyncJenkinsTemplate.slice(
defaultUpstreamAuditIndex,
firstUpstreamExecuteIndex === -1
? upstreamSyncJenkinsTemplate.length
: firstUpstreamExecuteIndex,
);
if (defaultUpstreamAuditCall.includes("--use-codex")) {
if (!unsafeDefaultUpstreamAuditRejected) {
throw new Error(
"NapCat upstream Jenkins template default audit must not use Codex",
"NapCat upstream Jenkins template unsafe default audit self-check failed",
);
}
for (const forbidden of ["git merge", "git push", "docker build", "kubectl"]) {
@ -517,6 +558,8 @@ export async function runSelfTest(): Promise<void> {
"string(name: 'API_PROMOTION_JOB'",
"git merge",
"git push",
"docker build",
"kubectl",
]) {
if (runtimeReleaseJenkinsTemplate.includes(forbidden)) {
throw new Error(