refactor: 프론트 템플릿 리펙토링

This commit is contained in:
donghyeon-ka
2026-09-18 15:16:58 +09:00
parent c10a709f2c
commit 5cc41467ae
80 changed files with 7227 additions and 4672 deletions
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,168 @@
import { spawnSync } from "node:child_process";
import { mkdir, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
import { tmpdir } from "node:os";
import path from "node:path";
import { afterEach, describe, expect, it } from "vitest";
import { loadCiGateContract } from "../../../scripts/contracts/ci-gates.ts";
const temporaryRoots: string[] = [];
afterEach(async () => {
await Promise.all(
temporaryRoots.splice(0).map((root) =>
rm(root, { recursive: true, force: true }),
),
);
});
describe("CI-runner command-generated evidence freshness", () => {
it("rejects stale command-generated evidence from a successful no-op producer", async () => {
const root = await mkdtemp(path.join(tmpdir(), "ci-gate-stale-evidence-"));
temporaryRoots.push(root);
await mkdir(path.join(root, "config/ci"), { recursive: true });
await mkdir(path.join(root, "artifacts/tests"), { recursive: true });
const contract = JSON.parse(
JSON.stringify(await loadCiGateContract(process.cwd())),
) as Record<string, any>;
const command = contract.commands.find(
(entry: Record<string, any>) => entry.id === "test-runtime-schema",
);
command.script = "test:stale-evidence-noop";
const evidence = contract.artifacts.find(
(entry: Record<string, any>) =>
entry.path === "artifacts/tests/runtime-schema.xml",
);
const packageDocument = JSON.parse(
await readFile("package.json", "utf8"),
) as { scripts: Record<string, string> };
packageDocument.scripts[command.script] = "true";
await writeFile(
path.join(root, "config/ci/gates.json"),
`${JSON.stringify(contract)}\n`,
);
await writeFile(
path.join(root, "package.json"),
`${JSON.stringify(packageDocument)}\n`,
);
await writeFile(
path.join(root, evidence.path),
'<testsuite name="stale" tests="0" failures="0"/>\n',
);
const result = spawnSync(
process.execPath,
[path.resolve("scripts/run-ci-gate.ts"), "FE-GATE-004"],
{ cwd: root, encoding: "utf8", env: { ...process.env, CI: "false" } },
);
expect(result.status).toBe(1);
expect(
await readFile(
path.join(root, "artifacts/quality/gates/FE-GATE-004.txt"),
"utf8",
),
).toMatch(/not freshly produced/i);
});
it("accepts a fresh deterministic rewrite with identical evidence bytes", async () => {
const root = await mkdtemp(
path.join(tmpdir(), "ci-gate-identical-rewrite-"),
);
temporaryRoots.push(root);
await mkdir(path.join(root, "config/ci"), { recursive: true });
await mkdir(path.join(root, "artifacts/tests"), { recursive: true });
const contract = JSON.parse(
JSON.stringify(await loadCiGateContract(process.cwd())),
) as Record<string, any>;
const command = contract.commands.find(
(entry: Record<string, any>) => entry.id === "test-runtime-schema",
);
command.script = "test:identical-evidence-rewrite";
const evidence = contract.artifacts.find(
(entry: Record<string, any>) =>
entry.path === "artifacts/tests/runtime-schema.xml",
);
const evidenceBytes =
'<testsuite name="deterministic" tests="0" failures="0"/>\n';
const packageDocument = JSON.parse(
await readFile("package.json", "utf8"),
) as { scripts: Record<string, string> };
packageDocument.scripts[command.script] =
`node -e 'require("node:fs").writeFileSync("${evidence.path}", Buffer.from("${Buffer.from(evidenceBytes).toString("base64")}", "base64"))'`;
await writeFile(
path.join(root, "config/ci/gates.json"),
`${JSON.stringify(contract)}\n`,
);
await writeFile(
path.join(root, "package.json"),
`${JSON.stringify(packageDocument)}\n`,
);
await writeFile(path.join(root, evidence.path), evidenceBytes);
const result = spawnSync(
process.execPath,
[path.resolve("scripts/run-ci-gate.ts"), "FE-GATE-004"],
{ cwd: root, encoding: "utf8", env: { ...process.env, CI: "false" } },
);
expect(result.status).toBe(0);
expect(result.stdout).toMatch(/FE-GATE-004 runtime-schema: PASS/);
});
});
describe("CI-runner gate output budget", () => {
it("caps aggregate gate output at the log schema before later commands can accumulate", async () => {
const root = await mkdtemp(path.join(tmpdir(), "ci-gate-output-budget-"));
temporaryRoots.push(root);
await mkdir(path.join(root, "config/ci"), { recursive: true });
const contract = JSON.parse(
JSON.stringify(await loadCiGateContract(process.cwd())),
) as Record<string, any>;
const gate = contract.gates.find(
(entry: Record<string, any>) => entry.id === "FE-GATE-001",
);
const command = contract.commands.find(
(entry: Record<string, any>) => entry.id === gate.commandIds[0],
);
command.script = "test:huge-output";
const logArtifact = contract.artifacts.find(
(entry: Record<string, any>) => entry.id === gate.logArtifactId,
);
const logSchema = contract.artifactSchemas.find(
(entry: Record<string, any>) => entry.id === logArtifact.schemaId,
);
logSchema.maxBytes = 8_192;
const packageDocument = JSON.parse(
await readFile("package.json", "utf8"),
) as { scripts: Record<string, string> };
packageDocument.scripts["test:huge-output"] =
"node -e \"process.stdout.write('x'.repeat(20000))\"";
await writeFile(
path.join(root, "config/ci/gates.json"),
`${JSON.stringify(contract)}\n`,
);
await writeFile(
path.join(root, "package.json"),
`${JSON.stringify(packageDocument)}\n`,
);
const result = spawnSync(
process.execPath,
[path.resolve("scripts/run-ci-gate.ts"), "FE-GATE-001"],
{
cwd: root,
encoding: "utf8",
env: { ...process.env, CI: "false" },
timeout: 15_000,
},
);
expect(result.status).toBe(1);
const log = await readFile(path.join(root, logArtifact.path));
expect(log.byteLength).toBeLessThanOrEqual(8_192);
expect(log.toString("utf8")).toMatch(
/aggregate output|INFRASTRUCTURE_FAILURE/i,
);
}, 20_000);
});
@@ -0,0 +1,41 @@
import { mkdtemp, readFile, rm } from "node:fs/promises";
import { tmpdir } from "node:os";
import path from "node:path";
import { describe, expect, it } from "vitest";
import { runProviderProcess } from "../../../scripts/lib/provider-process-runner.ts";
describe("CI-runner provider process-group lifecycle", () => {
it("kills and reaps a stubborn provider process group including its descendant", async () => {
const root = await mkdtemp(path.join(tmpdir(), "provider-process-group-"));
const descendantPidPath = path.join(root, "descendant.pid");
try {
const source = [
"const { spawn } = require('node:child_process');",
"const { writeFileSync } = require('node:fs');",
"const child = spawn(process.execPath, ['-e', `process.on('SIGTERM', () => {}); setInterval(() => {}, 1000)`], { stdio: 'ignore' });",
"writeFileSync(process.env.DESCENDANT_PID_PATH, String(child.pid));",
"process.on('SIGTERM', () => {});",
"setInterval(() => {}, 1000);",
].join("\n");
const running = runProviderProcess({
executable: process.execPath,
arguments: ["-e", source],
environment: {
PATH: process.env.PATH,
DESCENDANT_PID_PATH: descendantPidPath,
},
timeoutMs: 250,
});
await expect(running).rejects.toThrow(/timed out.*process close/u);
const descendantPid = Number(await readFile(descendantPidPath, "utf8"));
expect(Number.isSafeInteger(descendantPid) && descendantPid > 0).toBe(true);
expect(() => process.kill(descendantPid, 0)).toThrow(/ESRCH|no such process/u);
} finally {
await rm(root, { recursive: true, force: true });
}
});
});