78 lines
2.6 KiB
JavaScript
78 lines
2.6 KiB
JavaScript
#!/usr/bin/env node
|
|
// Restore the node/lane artifact catalog from the GitOps branch before CI planning.
|
|
|
|
import { execFileSync } from "node:child_process";
|
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
import { dirname } from "node:path";
|
|
|
|
const startedAt = Date.now();
|
|
|
|
function env(name) {
|
|
const value = process.env[name];
|
|
return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
|
|
}
|
|
|
|
function emit(payload) {
|
|
process.stderr.write(JSON.stringify({
|
|
event: "artifact-catalog-restore",
|
|
source: "scripts/ci/restore-artifact-catalog.mjs",
|
|
at: new Date().toISOString(),
|
|
durationMs: Date.now() - startedAt,
|
|
catalogPath,
|
|
gitopsBranch,
|
|
...payload
|
|
}) + "\n");
|
|
}
|
|
|
|
function catalogHasServices(filePath) {
|
|
if (!existsSync(filePath)) return false;
|
|
try {
|
|
const parsed = JSON.parse(readFileSync(filePath, "utf8"));
|
|
return Array.isArray(parsed?.services) && parsed.services.length > 0;
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
function git(args, options = {}) {
|
|
return execFileSync("git", args, {
|
|
cwd: process.cwd(),
|
|
encoding: "utf8",
|
|
stdio: options.capture === false ? ["ignore", "ignore", "pipe"] : ["ignore", "pipe", "pipe"],
|
|
timeout: options.timeoutMs ?? 45_000
|
|
});
|
|
}
|
|
|
|
const catalogPath = env("HWLAB_CATALOG_PATH");
|
|
const gitopsBranch = env("HWLAB_GITOPS_BRANCH");
|
|
const remote = env("HWLAB_GIT_READ_URL") ?? env("HWLAB_GIT_URL");
|
|
|
|
if (!catalogPath || !gitopsBranch || !remote) {
|
|
emit({ status: "skipped", reason: "required-input-missing", hasCatalogPath: Boolean(catalogPath), hasGitopsBranch: Boolean(gitopsBranch), hasRemote: Boolean(remote) });
|
|
process.exit(0);
|
|
}
|
|
|
|
if (catalogHasServices(catalogPath)) {
|
|
emit({ status: "source-present", reason: "catalog-already-present" });
|
|
process.exit(0);
|
|
}
|
|
|
|
try {
|
|
git(["fetch", "--depth=1", remote, `refs/heads/${gitopsBranch}`], { capture: false, timeoutMs: 60_000 });
|
|
const content = git(["show", `FETCH_HEAD:${catalogPath}`], { timeoutMs: 30_000 });
|
|
const parsed = JSON.parse(content);
|
|
if (!Array.isArray(parsed?.services) || parsed.services.length === 0) {
|
|
emit({ status: "skipped", reason: "gitops-catalog-has-no-services" });
|
|
process.exit(0);
|
|
}
|
|
mkdirSync(dirname(catalogPath), { recursive: true });
|
|
writeFileSync(catalogPath, JSON.stringify(parsed, null, 2) + "\n");
|
|
emit({ status: "restored", reason: "gitops-catalog", serviceCount: parsed.services.length, bytes: Buffer.byteLength(content) });
|
|
} catch (error) {
|
|
emit({
|
|
status: "skipped",
|
|
reason: "gitops-catalog-unavailable",
|
|
error: error instanceof Error ? error.message.slice(0, 500) : String(error).slice(0, 500)
|
|
});
|
|
}
|