fix: harden CI evidence and removal contracts
This commit is contained in:
@@ -1,25 +1,30 @@
|
||||
import { spawnSync } from "node:child_process";
|
||||
import {
|
||||
access,
|
||||
cp,
|
||||
mkdir,
|
||||
mkdtemp,
|
||||
readFile,
|
||||
readdir,
|
||||
rm,
|
||||
symlink,
|
||||
writeFile,
|
||||
} from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
|
||||
import { isProductionModulePath } from "./lib/risk-coverage.ts";
|
||||
import {
|
||||
filesBelow,
|
||||
prepareRemovalFixture,
|
||||
pruneRemovalFixtureCiContract,
|
||||
pruneScriptOrchestration,
|
||||
regenerateRemovalFixtureWorkflow,
|
||||
requireRemovalFixtureEnvironment,
|
||||
runRemovalFixturePnpm,
|
||||
} from "./lib/removal-fixture.ts";
|
||||
|
||||
const fixtureParent = path.resolve(".tmp");
|
||||
await mkdir(fixtureParent, { recursive: true });
|
||||
const fixtureRoot = await mkdtemp(
|
||||
path.join(fixtureParent, "reference-feature-removal-"),
|
||||
);
|
||||
const pnpmCli = requireEnvironment("npm_execpath");
|
||||
const pnpmCli = requireRemovalFixtureEnvironment("npm_execpath");
|
||||
const featureSource = "src/features/reference-feature";
|
||||
const featureTests = "tests/features/reference-feature";
|
||||
const commonTestPaths = [
|
||||
@@ -162,36 +167,20 @@ type GovernanceRegistry = Record<string, unknown> & {
|
||||
};
|
||||
type RemovalGovernance = { registries: GovernanceRegistry[] };
|
||||
|
||||
function requireEnvironment(name: string): string {
|
||||
const value = process.env[name];
|
||||
if (!value) throw new Error(`${name} is required for sample removal`);
|
||||
return value;
|
||||
}
|
||||
|
||||
async function filesBelow(directory: string): Promise<string[]> {
|
||||
const entries = await readdir(directory, { withFileTypes: true });
|
||||
const groups = await Promise.all(
|
||||
entries.map((entry) => {
|
||||
const target = path.join(directory, entry.name);
|
||||
return entry.isDirectory() ? filesBelow(target) : [target];
|
||||
}),
|
||||
);
|
||||
return groups.flat();
|
||||
}
|
||||
|
||||
function runPnpm(script: string, extra: string[] = []): boolean {
|
||||
const result = spawnSync(process.execPath, [pnpmCli, script, ...extra], {
|
||||
cwd: fixtureRoot,
|
||||
stdio: "inherit",
|
||||
});
|
||||
return result.status === 0;
|
||||
return runRemovalFixturePnpm(fixtureRoot, pnpmCli, script, extra);
|
||||
}
|
||||
|
||||
try {
|
||||
for (const target of copyTargets) {
|
||||
await cp(target, path.join(fixtureRoot, target), { recursive: true });
|
||||
await prepareRemovalFixture(fixtureRoot, copyTargets);
|
||||
for (const excludedFixtureTest of [
|
||||
"tests/unit/ci-workflow-generation.test.ts",
|
||||
"tests/unit/__snapshots__/ci-workflow-generation.test.ts.snap",
|
||||
"tests/unit/removal-fixture.test.ts",
|
||||
"tests/unit/http-scenario-evidence.test.ts",
|
||||
]) {
|
||||
await rm(path.join(fixtureRoot, excludedFixtureTest), { force: true });
|
||||
}
|
||||
await symlink(path.resolve("node_modules"), path.join(fixtureRoot, "node_modules"), "dir");
|
||||
|
||||
const coveragePolicyFile = path.join(
|
||||
fixtureRoot,
|
||||
@@ -329,6 +318,33 @@ try {
|
||||
`${JSON.stringify(removalGovernance, null, 2)}\n`,
|
||||
);
|
||||
|
||||
const removedCiScripts = new Set([
|
||||
"check:types:fixture:feature-input",
|
||||
"check:types:fixture:reference-operation",
|
||||
"test:http-scenario-evidence",
|
||||
"test:reference-feature",
|
||||
]);
|
||||
const fixturePackagePath = path.join(fixtureRoot, "package.json");
|
||||
const fixturePackage = JSON.parse(await readFile(fixturePackagePath, "utf8")) as {
|
||||
scripts: Record<string, string>;
|
||||
};
|
||||
pruneScriptOrchestration(fixturePackage.scripts, "test:all", removedCiScripts);
|
||||
fixturePackage.scripts["test:coverage"] = fixturePackage.scripts["test:coverage"]
|
||||
.replace(" tests/features/reference-feature", "");
|
||||
delete fixturePackage.scripts["check:http-scenario-evidence"];
|
||||
delete fixturePackage.scripts["check:http-scenario-evidence:fixture"];
|
||||
await writeFile(fixturePackagePath, `${JSON.stringify(fixturePackage, null, 2)}\n`);
|
||||
await pruneRemovalFixtureCiContract({
|
||||
root: fixtureRoot,
|
||||
removedScripts: removedCiScripts,
|
||||
removedEvidencePathFragments: [
|
||||
"reference-feature.xml",
|
||||
"http-scenario-executions",
|
||||
"http-scenario-evidence",
|
||||
],
|
||||
});
|
||||
await regenerateRemovalFixtureWorkflow(fixtureRoot);
|
||||
|
||||
const residue: string[] = [];
|
||||
for (const root of ["src", "tests"]) {
|
||||
for (const file of await filesBelow(path.join(fixtureRoot, root))) {
|
||||
@@ -366,6 +382,7 @@ try {
|
||||
["unit-integration", runPnpm("test:all")],
|
||||
["coverage", runPnpm("test:coverage")],
|
||||
["test-evidence-source", runPnpm("check:test-evidence:source")],
|
||||
["ci-contract", runPnpm("check:ci")],
|
||||
[
|
||||
"home-smoke",
|
||||
runPnpm("exec", [
|
||||
|
||||
Reference in New Issue
Block a user