73 lines
1.7 KiB
JavaScript
73 lines
1.7 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
import { spawn } from "node:child_process";
|
|
|
|
const baseUrl = process.env.SMOKE_BASE_URL || "";
|
|
const skipSmoke = process.argv.includes("--skip-smoke");
|
|
|
|
const steps = [
|
|
{
|
|
name: "quality gate",
|
|
command: "pnpm",
|
|
args: ["check:quality"],
|
|
},
|
|
{
|
|
name: "dependency audit",
|
|
command: "pnpm",
|
|
args: ["audit:security"],
|
|
},
|
|
{
|
|
name: "production build",
|
|
command: "pnpm",
|
|
args: ["build"],
|
|
},
|
|
];
|
|
|
|
if (baseUrl) {
|
|
steps.push({
|
|
name: "route smoke",
|
|
command: "pnpm",
|
|
args: ["smoke:routes"],
|
|
});
|
|
} else if (!skipSmoke) {
|
|
console.error(
|
|
[
|
|
"Release verification requires SMOKE_BASE_URL so route smoke tests run against an explicit target.",
|
|
"Example:",
|
|
" SMOKE_BASE_URL=http://127.0.0.1:3001 pnpm verify:release",
|
|
"Use `pnpm verify:release -- --skip-smoke` only for documentation or CI dry-runs where no app is running.",
|
|
].join("\n")
|
|
);
|
|
process.exit(1);
|
|
}
|
|
|
|
for (const [index, step] of steps.entries()) {
|
|
console.log(`\n[release:${index + 1}/${steps.length}] ${step.name}`);
|
|
await run(step.command, step.args);
|
|
}
|
|
|
|
if (skipSmoke && !baseUrl) {
|
|
console.warn("\n[release] route smoke skipped by explicit --skip-smoke flag.");
|
|
}
|
|
|
|
console.log("\nRelease verification passed.");
|
|
|
|
function run(command, args) {
|
|
return new Promise((resolve, reject) => {
|
|
const child = spawn(command, args, {
|
|
env: process.env,
|
|
shell: false,
|
|
stdio: "inherit",
|
|
});
|
|
|
|
child.on("error", reject);
|
|
child.on("exit", (code) => {
|
|
if (code === 0) {
|
|
resolve();
|
|
return;
|
|
}
|
|
reject(new Error(`${command} ${args.join(" ")} failed with exit code ${code}`));
|
|
});
|
|
});
|
|
}
|