refactor: split GitOps renderer by responsibility
This commit is contained in:
@@ -0,0 +1,187 @@
|
||||
import { readFileSync } from "node:fs";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
import {
|
||||
ciToolsRunnerImage,
|
||||
defaultServiceIds,
|
||||
defaultV02RuntimeEndpoint,
|
||||
primitiveValidationTasks,
|
||||
proxyEnv
|
||||
} from "./core.mjs";
|
||||
|
||||
const templatesDir = path.join(path.dirname(fileURLToPath(import.meta.url)), "templates");
|
||||
const templateCache = new Map();
|
||||
|
||||
function readTemplate(name) {
|
||||
if (!templateCache.has(name)) {
|
||||
templateCache.set(name, readFileSync(path.join(templatesDir, name), "utf8"));
|
||||
}
|
||||
return templateCache.get(name);
|
||||
}
|
||||
|
||||
function renderTemplate(name, replacements = {}) {
|
||||
let rendered = readTemplate(name);
|
||||
for (const [token, value] of Object.entries(replacements)) {
|
||||
if (!rendered.includes(token)) throw new Error(`template ${name} is missing token ${token}`);
|
||||
rendered = rendered.replaceAll(token, String(value));
|
||||
}
|
||||
const unresolved = [...rendered.matchAll(/__HWLAB_[A-Z0-9_]+__/gu)].map((match) => match[0]);
|
||||
if (unresolved.length > 0) {
|
||||
throw new Error(`template ${name} has unresolved tokens: ${[...new Set(unresolved)].join(", ")}`);
|
||||
}
|
||||
return rendered;
|
||||
}
|
||||
|
||||
function shellSingleQuote(value) {
|
||||
return `'${String(value).replace(/'/g, `'"'"'`)}'`;
|
||||
}
|
||||
|
||||
function ciTimingShellFunction() {
|
||||
return readTemplate("ci-timing-functions.sh");
|
||||
}
|
||||
|
||||
function dependencyProxyProbeScript(phase, targetUrl) {
|
||||
if (!/^[a-z0-9-]+$/u.test(phase)) throw new Error(`invalid dependency proxy probe phase: ${phase}`);
|
||||
return renderTemplate("dependency-proxy-probe.sh", {
|
||||
"__HWLAB_PROXY_PHASE_SHELL__": shellSingleQuote(phase),
|
||||
"__HWLAB_PROXY_TARGET_SHELL__": shellSingleQuote(targetUrl),
|
||||
"__HWLAB_PROXY_PHASE__": phase
|
||||
});
|
||||
}
|
||||
|
||||
function curlDownloadProbeFunction() {
|
||||
return readTemplate("curl-download-probe.sh");
|
||||
}
|
||||
|
||||
function gitSshShellFunction() {
|
||||
return renderTemplate("git-ssh-functions.sh", {
|
||||
"// __HWLAB_GITHUB_PROXY_CONNECT_MJS__": readTemplate("github-proxy-connect.mjs")
|
||||
});
|
||||
}
|
||||
|
||||
function prepareSourceScript() {
|
||||
return renderTemplate("prepare-source.sh", {
|
||||
"# __HWLAB_CI_TIMING_SHELL__\n": ciTimingShellFunction(),
|
||||
"# __HWLAB_GIT_SSH_SHELL__\n": gitSshShellFunction(),
|
||||
"__HWLAB_CI_TOOLS_IMAGE__": ciToolsRunnerImage,
|
||||
"__HWLAB_V02_RUNTIME_ENDPOINT__": JSON.stringify(defaultV02RuntimeEndpoint).slice(1, -1),
|
||||
"__HWLAB_VALIDATION_TASK_COUNT__": primitiveValidationTasks.length
|
||||
});
|
||||
}
|
||||
|
||||
function sourceValidationScript(commands) {
|
||||
return [
|
||||
"#!/bin/sh",
|
||||
"set -eu",
|
||||
"git config --global --add safe.directory /workspace/source/repo",
|
||||
"cd /workspace/source/repo",
|
||||
"test \"$(git rev-parse HEAD)\" = \"$(params.revision)\"",
|
||||
...commands
|
||||
].join("\n") + "\n";
|
||||
}
|
||||
|
||||
function primitiveValidationTaskNames() {
|
||||
return primitiveValidationTasks.map((task) => task.name);
|
||||
}
|
||||
|
||||
function primitiveValidationTask(task) {
|
||||
return {
|
||||
name: task.name,
|
||||
runAfter: ["prepare-source"],
|
||||
workspaces: [{ name: "source", workspace: "source" }],
|
||||
taskSpec: {
|
||||
params: [
|
||||
{ name: "revision" },
|
||||
{ name: "lane" },
|
||||
{ name: "catalog-path" },
|
||||
{ name: "image-tag-mode" },
|
||||
{ name: "source-branch" },
|
||||
{ name: "gitops-branch" }
|
||||
],
|
||||
workspaces: [{ name: "source" }],
|
||||
steps: [{ name: task.name, image: ciToolsRunnerImage, env: proxyEnv(), script: sourceValidationScript(task.commands) }]
|
||||
},
|
||||
params: [
|
||||
{ name: "revision", value: "$(params.revision)" },
|
||||
{ name: "lane", value: "$(params.lane)" },
|
||||
{ name: "catalog-path", value: "$(params.catalog-path)" },
|
||||
{ name: "image-tag-mode", value: "$(params.image-tag-mode)" },
|
||||
{ name: "source-branch", value: "$(params.source-branch)" },
|
||||
{ name: "gitops-branch", value: "$(params.gitops-branch)" }
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
function planArtifactsScript() {
|
||||
return renderTemplate("plan-artifacts.sh", {
|
||||
"__HWLAB_CI_TOOLS_IMAGE__": ciToolsRunnerImage,
|
||||
'["__HWLAB_DEFAULT_SERVICE_IDS__"]': JSON.stringify(defaultServiceIds)
|
||||
});
|
||||
}
|
||||
|
||||
function perServicePublishScript() {
|
||||
return renderTemplate("per-service-publish.sh", {
|
||||
"# __HWLAB_CI_TIMING_SHELL__\n": ciTimingShellFunction(),
|
||||
"# __HWLAB_DEPENDENCY_PROXY_PROBE__": dependencyProxyProbeScript(
|
||||
"service-image-publish-proxy-preflight",
|
||||
"http://deb.debian.org/debian/dists/bookworm/InRelease"
|
||||
),
|
||||
"__HWLAB_CI_TOOLS_IMAGE__": ciToolsRunnerImage
|
||||
});
|
||||
}
|
||||
|
||||
function collectArtifactsScript() {
|
||||
return renderTemplate("collect-artifacts.sh", {
|
||||
"__HWLAB_CI_TOOLS_IMAGE__": ciToolsRunnerImage
|
||||
});
|
||||
}
|
||||
|
||||
function gitopsPromoteScript() {
|
||||
return renderTemplate("gitops-promote.sh", {
|
||||
"# __HWLAB_CI_TIMING_SHELL__\n": ciTimingShellFunction(),
|
||||
"# __HWLAB_GIT_SSH_SHELL__\n": gitSshShellFunction(),
|
||||
"__HWLAB_CI_TOOLS_IMAGE__": ciToolsRunnerImage
|
||||
});
|
||||
}
|
||||
|
||||
function controlPlaneReconcileScript() {
|
||||
return renderTemplate("control-plane-reconcile.sh", {
|
||||
"# __HWLAB_DEPENDENCY_PROXY_PROBE__": dependencyProxyProbeScript(
|
||||
"control-plane-proxy-preflight",
|
||||
"http://deb.debian.org/debian/dists/bookworm/InRelease"
|
||||
),
|
||||
"# __HWLAB_GIT_SSH_SHELL__\n": gitSshShellFunction(),
|
||||
"__HWLAB_CI_TOOLS_IMAGE__": ciToolsRunnerImage
|
||||
});
|
||||
}
|
||||
|
||||
function pollerScript() {
|
||||
return renderTemplate("poller.sh", {
|
||||
"# __HWLAB_DEPENDENCY_PROXY_PROBE__": dependencyProxyProbeScript(
|
||||
"poller-proxy-preflight",
|
||||
"http://deb.debian.org/debian/dists/bookworm/InRelease"
|
||||
),
|
||||
"# __HWLAB_GIT_SSH_SHELL__\n": gitSshShellFunction(),
|
||||
"__HWLAB_CI_TOOLS_IMAGE__": ciToolsRunnerImage
|
||||
});
|
||||
}
|
||||
|
||||
export {
|
||||
ciTimingShellFunction,
|
||||
collectArtifactsScript,
|
||||
controlPlaneReconcileScript,
|
||||
curlDownloadProbeFunction,
|
||||
dependencyProxyProbeScript,
|
||||
gitopsPromoteScript,
|
||||
gitSshShellFunction,
|
||||
perServicePublishScript,
|
||||
planArtifactsScript,
|
||||
pollerScript,
|
||||
prepareSourceScript,
|
||||
primitiveValidationTask,
|
||||
primitiveValidationTaskNames,
|
||||
renderTemplate,
|
||||
shellSingleQuote,
|
||||
sourceValidationScript
|
||||
};
|
||||
Reference in New Issue
Block a user