import { readFile } from "node:fs/promises"; import path from "node:path"; import assert from "node:assert/strict"; import type { SelfTestCase } from "../harness.js"; type InlineTaskSpecContract = { taskName: string; requiredParams: string[]; providedParams: string[]; }; const selfTest: SelfTestCase = async (context) => { const text = await readFile(path.join(context.root, "deploy/templates/tekton/pipeline.yaml"), "utf8"); const tasks = inlineTaskSpecContracts(text); for (const task of tasks) { const provided = new Set(task.providedParams); for (const name of task.requiredParams) { assert.equal(provided.has(name), true, `pipeline task ${task.taskName} must pass taskSpec param ${name}`); } } return { name: "80-cicd-tekton-contract", tests: ["inline taskSpec params are passed by every pipeline task"] }; }; function inlineTaskSpecContracts(text: string): InlineTaskSpecContract[] { const tasks: InlineTaskSpecContract[] = []; let current: InlineTaskSpecContract | null = null; let inTasks = false; let inTaskSpec = false; let section: "taskSpecParams" | "taskParams" | null = null; for (const rawLine of text.split(/\r?\n/u)) { const line = rawLine.replace(/\s+$/u, ""); const trimmed = line.trim(); const indent = line.length - line.trimStart().length; if (line === " tasks:") { inTasks = true; continue; } if (!inTasks || trimmed.length === 0 || trimmed.startsWith("#")) continue; const taskMatch = /^ - name: (.+)$/u.exec(line); if (taskMatch) { if (current) tasks.push(current); current = { taskName: taskMatch[1] ?? "", requiredParams: [], providedParams: [] }; inTaskSpec = false; section = null; continue; } if (!current) continue; if (indent === 6 && trimmed === "taskSpec:") { inTaskSpec = true; section = null; continue; } if (indent === 6 && trimmed === "params:") { inTaskSpec = false; section = "taskParams"; continue; } if (indent === 8 && inTaskSpec && trimmed === "params:") { section = "taskSpecParams"; continue; } if ((section === "taskSpecParams" && indent <= 8) || (section === "taskParams" && indent <= 6)) { section = null; } const paramMatch = /^\s*- name: (.+)$/u.exec(line); if (!paramMatch || !section) continue; const name = paramMatch[1] ?? ""; if (section === "taskSpecParams") current.requiredParams.push(name); if (section === "taskParams") current.providedParams.push(name); } if (current) tasks.push(current); return tasks; } export default selfTest;