fix(cicd): inject runtime gitops guard in native refresh
This commit is contained in:
@@ -15,6 +15,7 @@ const gitReadUrl = requiredEnv("GIT_READ_URL");
|
||||
const fieldManager = requiredEnv("FIELD_MANAGER");
|
||||
const tektonNamespace = requiredEnv("TEKTON_NAMESPACE");
|
||||
const kubeRequestTimeoutSeconds = requiredEnvPositiveNumber("KUBE_REQUEST_TIMEOUT_SECONDS");
|
||||
const runtimeGitopsConfigMapName = requiredEnv("RUNTIME_GITOPS_CONFIGMAP_NAME");
|
||||
const overlay = JSON.parse(Buffer.from(requiredEnv("HWLAB_RENDER_OVERLAY_B64"), "base64").toString("utf8"));
|
||||
const workDir = mkdtempSync(path.join(tmpdir(), `hwlab-control-plane-${sourceCommit.slice(0, 12)}-`));
|
||||
const repoDir = path.join(workDir, "repo");
|
||||
@@ -143,7 +144,8 @@ async function applyPipeline() {
|
||||
if (typeof renderedPipelineName !== "string" || renderedPipelineName.length === 0) {
|
||||
throw new Error(`rendered Pipeline metadata.name missing: ${pipelinePath}`);
|
||||
}
|
||||
const render = summarizeRenderedPipeline(pipeline, renderedPipelineName);
|
||||
const runtimeGitopsGuard = injectRuntimeGitopsGuard(pipeline);
|
||||
const render = summarizeRenderedPipeline(pipeline, renderedPipelineName, runtimeGitopsGuard);
|
||||
const pipelineName = requiredOverlayString("pipelineName");
|
||||
pipeline.metadata = pipeline.metadata && typeof pipeline.metadata === "object" ? pipeline.metadata : {};
|
||||
pipeline.metadata.name = pipelineName;
|
||||
@@ -286,13 +288,82 @@ function requiredNonNegativeNumber(name) {
|
||||
return Math.floor(value);
|
||||
}
|
||||
|
||||
function summarizeRenderedPipeline(pipeline, pipelineName) {
|
||||
function injectRuntimeGitopsGuard(pipeline) {
|
||||
const tasks = Array.isArray(pipeline?.spec?.tasks) ? pipeline.spec.tasks : [];
|
||||
const task = tasks.find((item) => recordOrNull(item)?.name === "gitops-promote");
|
||||
if (!task) throw new Error("runtime GitOps guard injection failed: gitops-promote task missing");
|
||||
const taskSpec = recordOrNull(task.taskSpec);
|
||||
if (taskSpec === null) throw new Error("runtime GitOps guard injection failed: gitops-promote taskSpec missing");
|
||||
const steps = Array.isArray(taskSpec.steps) ? taskSpec.steps : [];
|
||||
const step = steps.find((item) => typeof recordOrNull(item)?.script === "string" && item.script.includes("scripts/gitops-render.mjs"));
|
||||
if (!step) throw new Error("runtime GitOps guard injection failed: gitops-promote render step missing");
|
||||
const originalScript = String(step.script);
|
||||
let script = patchNoBuildNoRolloutSkip(originalScript);
|
||||
const noBuildSkipPatched = script !== originalScript;
|
||||
const beforeInjection = script;
|
||||
script = injectRuntimeGitopsCommands(script);
|
||||
const postprocessInjected = !beforeInjection.includes("runtime-gitops-postprocess.mjs") && script.includes("runtime-gitops-postprocess.mjs");
|
||||
const verifyInjected = !beforeInjection.includes("runtime-gitops-verify.mjs") && script.includes("runtime-gitops-verify.mjs");
|
||||
if (!script.includes("runtime-gitops-postprocess.mjs") || !script.includes("runtime-gitops-verify.mjs")) {
|
||||
throw new Error("runtime GitOps guard injection failed: postprocess/verify commands missing after patch");
|
||||
}
|
||||
step.script = script;
|
||||
ensureRuntimeGitopsScriptsMount(taskSpec, step);
|
||||
return {
|
||||
present: true,
|
||||
configMapName: runtimeGitopsConfigMapName,
|
||||
stepName: stringOrNull(step.name),
|
||||
noBuildSkipPatched,
|
||||
postprocessInjected,
|
||||
verifyInjected,
|
||||
};
|
||||
}
|
||||
|
||||
function patchNoBuildNoRolloutSkip(script) {
|
||||
return String(script).replace(
|
||||
/(^|\n)([ \t]*)echo '\{"event":"gitops-promote","status":"skipped","reason":"no-build-no-rollout-plan"\}'\n[ \t]*exit 0(?=\n|$)/u,
|
||||
(_match, prefix, indent) => `${prefix}${indent}echo '{"event":"gitops-promote","status":"continuing","reason":"no-build-no-rollout-plan-gitops-verify"}'`,
|
||||
);
|
||||
}
|
||||
|
||||
function injectRuntimeGitopsCommands(script) {
|
||||
if (script.includes("runtime-gitops-postprocess.mjs") && script.includes("runtime-gitops-verify.mjs")) return script;
|
||||
const overlayEnv = `UNIDESK_RUNTIME_GITOPS_OVERLAY_B64=${shellSingle(Buffer.from(JSON.stringify(overlay), "utf8").toString("base64"))}`;
|
||||
const postprocess = `${overlayEnv} node /etc/unidesk-cicd-runtime-gitops/runtime-gitops-postprocess.mjs`;
|
||||
const verify = `${overlayEnv} node /etc/unidesk-cicd-runtime-gitops/runtime-gitops-verify.mjs`;
|
||||
return String(script).replace(
|
||||
/(node scripts\/run-bun\.mjs scripts\/gitops-render\.mjs[^\n]*--use-deploy-images[^\n]*)/g,
|
||||
(match) => {
|
||||
if (match.includes("--check")) return `${match}\n${verify}`;
|
||||
return `${match}\n${postprocess}`;
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
function ensureRuntimeGitopsScriptsMount(taskSpec, step) {
|
||||
const volumeName = "unidesk-runtime-gitops-scripts";
|
||||
taskSpec.volumes = Array.isArray(taskSpec.volumes) ? taskSpec.volumes : [];
|
||||
if (!taskSpec.volumes.some((item) => recordOrNull(item)?.name === volumeName)) {
|
||||
taskSpec.volumes.push({ name: volumeName, configMap: { name: runtimeGitopsConfigMapName, defaultMode: 0o755 } });
|
||||
}
|
||||
step.volumeMounts = Array.isArray(step.volumeMounts) ? step.volumeMounts : [];
|
||||
if (!step.volumeMounts.some((item) => recordOrNull(item)?.name === volumeName)) {
|
||||
step.volumeMounts.push({ name: volumeName, mountPath: "/etc/unidesk-cicd-runtime-gitops", readOnly: true });
|
||||
}
|
||||
}
|
||||
|
||||
function shellSingle(value) {
|
||||
return `'${String(value).replaceAll("'", "'\\''")}'`;
|
||||
}
|
||||
|
||||
function summarizeRenderedPipeline(pipeline, pipelineName, runtimeGitopsGuard) {
|
||||
const tasks = Array.isArray(pipeline?.spec?.tasks) ? pipeline.spec.tasks : [];
|
||||
const runtimeReady = tasks.find((task) => recordOrNull(task)?.name === "runtime-ready");
|
||||
return {
|
||||
pipelineName,
|
||||
taskCount: tasks.length,
|
||||
runtimeReadyTask: summarizeRuntimeReadyTask(runtimeReady),
|
||||
runtimeGitopsGuard,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user