188 lines
5.8 KiB
JavaScript
188 lines
5.8 KiB
JavaScript
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
|
|
};
|