goodgrief/scripts/reset-production.mjs

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.");
}