Gitea Actions Runner Test / test-job (push) Successful in 1s
CI / check (push) Successful in 31s
CI / tests-unit (push) Successful in 1m57s
CI / tests-integration (push) Successful in 2m1s
CI / tests-ui (push) Successful in 2m51s
CI / preflight (push) Skipped
CI / deploy (push) Successful in 1m42s
Seven suites read .env with a bare `process.env[key] = value`, which overwrites whatever the shell already set. That made the DATABASE_URL from the production .env authoritative, so a single environment variable was enough to aim them at the live hotel database: RUN_CATALOG_AUDIT_LIVE=1 pnpm vitest run src/lib/services/catalog-audit-repair-live.test.ts Three of those suites then repair the catalog in place: catalog-audit-repair-live and catalog-repair-direct-live rewrite catalog_items and delete duplicate classnames, and clone-bulk-import-live bulk-imports every cloneable item. None of that is undoable, and nothing in their output said the target was production rather than a sandbox. Added src/test/live-env.ts with one shared loader, and pointed all seven suites at it: - Values already in the real environment win, so an explicit DATABASE_URL on the command line is always respected. - DATABASE_URL defaults to the sandbox on port 3307 rather than inheriting the production one from .env. - Anything that is not loopback is treated as production and redirected. - Reaching production requires ALLOW_PRODUCTION_LIVE_DB=1 and logs a warning saying the suite repairs the catalog. Tests in src/test/live-env.test.ts run the loader against a temporary .env so the real project file is never read, and cover the redirect, the shell override, non-loopback detection, the opt-in and quote stripping. A second block asserts each of the seven suites no longer contains an inline `process.env[...] =` assignment. Verified four of them fail against the old loader. This does not enable the suites; they stay gated behind their RUN_* flags. It only removes the possibility of them silently hitting production. Unit suite: 3330 passed, 12 skipped. Typecheck and lint clean.
55 lines
1.6 KiB
TypeScript
55 lines
1.6 KiB
TypeScript
// @ts-nocheck
|
|
// Read-only audit run that writes the full summary to a log file.
|
|
import { appendFileSync } from "node:fs";
|
|
import { beforeAll, describe, expect, it } from "vitest";
|
|
import { loadEnvForLiveTests } from "@/test/live-env";
|
|
|
|
const runLive = process.env.RUN_CATALOG_AUDIT_LIVE === "1";
|
|
const LOG = "/tmp/catalog-audit-summary.log";
|
|
const log = (msg: string) => {
|
|
appendFileSync(LOG, `${msg}\n`);
|
|
};
|
|
|
|
describe.skipIf(!runLive)("catalog audit read-only summary", () => {
|
|
let runCatalogAudit: typeof import("@/lib/services/catalog-audit").runCatalogAudit;
|
|
|
|
beforeAll(async () => {
|
|
loadEnvForLiveTests();
|
|
|
|
const auditMod = await import("@/lib/services/catalog-audit");
|
|
runCatalogAudit = auditMod.runCatalogAudit;
|
|
});
|
|
|
|
it("reports the full audit summary", async () => {
|
|
expect(process.env.DATABASE_URL).toMatch(/@/);
|
|
|
|
const events: Array<Record<string, unknown>> = [];
|
|
await runCatalogAudit(
|
|
(evt) => events.push(evt as unknown as Record<string, unknown>),
|
|
{},
|
|
);
|
|
|
|
const last = events[events.length - 1];
|
|
expect(last?.type).toBe("batch_complete");
|
|
const summary = last.summary as Record<string, unknown>;
|
|
const issues = last.issues as Array<{
|
|
type: string;
|
|
severity: string;
|
|
message: string;
|
|
classname?: string;
|
|
}>;
|
|
const unrepairable = last.unrepairable as Array<{
|
|
classname: string;
|
|
itemId: number;
|
|
missing: Array<string>;
|
|
}>;
|
|
|
|
log("=== SUMMARY ===");
|
|
log(JSON.stringify(summary, null, 2));
|
|
log("=== ISSUES ===");
|
|
log(JSON.stringify(issues, null, 2));
|
|
log("=== UNREPAIRABLE ===");
|
|
log(JSON.stringify(unrepairable, null, 2));
|
|
}, 300000);
|
|
});
|