117 lines
3.3 KiB
JavaScript
117 lines
3.3 KiB
JavaScript
import { spawnSync } from "node:child_process";
|
|
import path from "node:path";
|
|
import { fileURLToPath } from "node:url";
|
|
|
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
const repoRoot = path.resolve(__dirname, "..");
|
|
|
|
const args = new Set(process.argv.slice(2));
|
|
|
|
if (args.has("--help") || args.has("-h")) {
|
|
console.log(`Reset production runtime data for the container stack.
|
|
|
|
Usage:
|
|
npm run reset:prod
|
|
npm run reset:prod -- --keep-down
|
|
npm run reset:prod -- --tool=docker
|
|
npm run reset:prod -- --tool=podman
|
|
|
|
Options:
|
|
--keep-down Do not restart the stack after reset.
|
|
--tool=<name> Force compose tool: docker or podman.
|
|
--help, -h Show this help output.
|
|
`);
|
|
process.exit(0);
|
|
}
|
|
|
|
const forcedToolArg = [...args].find((arg) => arg.startsWith("--tool="));
|
|
const forcedTool = forcedToolArg ? forcedToolArg.slice("--tool=".length) : null;
|
|
const keepDown = args.has("--keep-down");
|
|
|
|
function run(command, commandArgs, options = {}) {
|
|
const result = spawnSync(command, commandArgs, {
|
|
cwd: repoRoot,
|
|
stdio: options.capture ? ["ignore", "pipe", "pipe"] : "inherit",
|
|
encoding: "utf8"
|
|
});
|
|
|
|
if (options.allowFailure) {
|
|
return result;
|
|
}
|
|
|
|
if (result.status !== 0) {
|
|
const stderr = result.stderr?.trim();
|
|
throw new Error(
|
|
stderr
|
|
? `${command} ${commandArgs.join(" ")} failed: ${stderr}`
|
|
: `${command} ${commandArgs.join(" ")} failed with exit code ${result.status ?? "unknown"}`
|
|
);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
function composeCommandFor(tool) {
|
|
if (tool === "docker") {
|
|
return ["docker", ["compose"]];
|
|
}
|
|
if (tool === "podman") {
|
|
return ["podman", ["compose"]];
|
|
}
|
|
throw new Error(`Unsupported compose tool: ${tool}`);
|
|
}
|
|
|
|
function detectComposeTool() {
|
|
const candidates = forcedTool ? [forcedTool] : ["docker", "podman"];
|
|
|
|
for (const candidate of candidates) {
|
|
const [command, baseArgs] = composeCommandFor(candidate);
|
|
const probe = run(command, [...baseArgs, "version"], { allowFailure: true, capture: true });
|
|
if (probe.status === 0) {
|
|
return { tool: candidate, command, baseArgs };
|
|
}
|
|
}
|
|
|
|
throw new Error("Could not find a working compose tool. Install Docker Compose or Podman Compose, or pass --tool=docker|podman.");
|
|
}
|
|
|
|
const composeTool = detectComposeTool();
|
|
const composeArgs = [
|
|
...composeTool.baseArgs,
|
|
"-f",
|
|
"docker-compose.yml",
|
|
"-f",
|
|
"docker-compose.prod.yml"
|
|
];
|
|
const services = ["api", "worker", "admin", "submission"];
|
|
|
|
function compose(commandArgs, options) {
|
|
return run(composeTool.command, [...composeArgs, ...commandArgs], options);
|
|
}
|
|
|
|
console.log(`Using ${composeTool.tool} compose.`);
|
|
|
|
const psResult = compose(["ps", "-q"], { capture: true, allowFailure: true });
|
|
const wasRunning = psResult.status === 0 && psResult.stdout.trim().length > 0;
|
|
|
|
if (wasRunning) {
|
|
console.log("Stopping production stack...");
|
|
compose(["down"]);
|
|
}
|
|
|
|
console.log("Clearing production runtime data...");
|
|
compose(["run", "--rm", "api", "npm", "run", "reset:runtime"]);
|
|
|
|
if (wasRunning && !keepDown) {
|
|
console.log("Restarting production stack...");
|
|
compose(["up", "-d", ...services]);
|
|
}
|
|
|
|
if (!wasRunning) {
|
|
console.log("Production stack was not running. Data is reset and the stack remains down.");
|
|
} else if (keepDown) {
|
|
console.log("Production stack was stopped for reset and left down.");
|
|
} else {
|
|
console.log("Production stack reset and restarted.");
|
|
}
|