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 };