diff --git a/deploy/trialrun/validate-env-contract.js b/deploy/trialrun/validate-env-contract.js index 72e44a8f..6f96204f 100755 --- a/deploy/trialrun/validate-env-contract.js +++ b/deploy/trialrun/validate-env-contract.js @@ -326,6 +326,7 @@ const trackedFiles = childProcess.execFileSync('git', ['ls-files', '--cached', ' const literalWebhookPattern = /https:\/\/qyapi\.weixin\.qq\.com\/cgi-bin\/webhook\/send\?key=/; for (const relativePath of trackedFiles) { const filePath = path.join(rootDir, relativePath); + if (!fs.existsSync(filePath)) continue; if (!fs.statSync(filePath).isFile()) continue; const content = fs.readFileSync(filePath); if (content.includes(0)) continue; diff --git a/server/tests/unit/scripts/env-recovery-classification.test.js b/server/tests/unit/scripts/env-recovery-classification.test.js index 7d91a236..28a42272 100644 --- a/server/tests/unit/scripts/env-recovery-classification.test.js +++ b/server/tests/unit/scripts/env-recovery-classification.test.js @@ -45,6 +45,17 @@ describe("environment recovery classification contract", () => { expect(result.stdout).toContain("环境恢复分类键数: 164"); }); + it("skips tracked paths deleted in the current worktree before reading metadata", async () => { + const source = await readFile(VALIDATOR, "utf8"); + const trackedFileLoop = source.indexOf("for (const relativePath of trackedFiles)"); + const existsGuard = source.indexOf("if (!fs.existsSync(filePath)) continue;", trackedFileLoop); + const statRead = source.indexOf("fs.statSync(filePath)", trackedFileLoop); + + expect(trackedFileLoop).toBeGreaterThanOrEqual(0); + expect(existsGuard).toBeGreaterThan(trackedFileLoop); + expect(statRead).toBeGreaterThan(existsGuard); + }); + it("rejects a missing key", async () => { const classification = structuredClone(baseClassification); classification.categories.template_rebuild = classification.categories.template_rebuild