Files
Jeppe B a930bd35a5 Add atomic cPanel frontend deployment (#178)
Build and archive the tested frontend, upload it through dedicated FTPS credentials, and atomically activate it through cPanel after CI succeeds.
2026-07-20 13:53:49 +02:00

48 lines
1.6 KiB
JavaScript

#!/usr/bin/env node
import fs from "node:fs/promises";
import path from "node:path";
import { DeploymentError } from "./cpanel-deploy-lib.mjs";
import { auditRoot, readRootConfig, restoreRoot } from "./cpanel-root-lib.mjs";
async function writeReport(report) {
const reportPath = process.env.CPANEL_ROOT_REPORT_PATH;
if (!reportPath) return;
await fs.mkdir(path.dirname(reportPath), { recursive: true });
await fs.writeFile(reportPath, `${JSON.stringify(report, null, 2)}\n`);
}
async function main() {
const mode = process.argv[2] || "audit";
if (!new Set(["audit", "restore"]).has(mode) || process.argv.length > 3) {
throw new DeploymentError("Usage: cpanel-root.mjs [audit|restore]");
}
const config = readRootConfig(process.env);
if (mode === "audit") {
const report = await auditRoot(config);
await writeReport(report);
console.log(JSON.stringify(report, null, 2));
if (process.env.GITHUB_OUTPUT) {
await fs.appendFile(
process.env.GITHUB_OUTPUT,
`healthy=${report.healthy}\nstate_token=${report.stateToken}\nrecovery_count=${report.recoveryCandidates.length}\n`
);
}
return;
}
const result = await restoreRoot(
config,
process.env.CPANEL_ROOT_RECOVERY || "",
process.env.CPANEL_ROOT_STATE_TOKEN || "",
process.env.CPANEL_ROOT_CONFIRMATION || ""
);
await writeReport(result);
console.log(`Restored ${result.restored}; retained displaced state as ${result.displaced}.`);
}
main().catch((error) => {
console.error(error instanceof Error ? error.message : "Unknown cPanel root failure.");
process.exit(1);
});