fix: tighten branch follower gate runtime inputs
This commit is contained in:
@@ -3,6 +3,7 @@ import { execFileSync } from "node:child_process";
|
||||
import { existsSync, readFileSync } from "node:fs";
|
||||
import http from "node:http";
|
||||
import https from "node:https";
|
||||
import { parseRuntimeReuseConfig, summarizeRuntimeReuseConfig } from "./reuse-config-summary.mjs";
|
||||
|
||||
const gate = requiredEnv("GATE");
|
||||
const follower = requiredEnv("FOLLOWER_ID");
|
||||
@@ -19,6 +20,8 @@ const argoApplication = process.env.ARGO_APPLICATION || "";
|
||||
const runtimeNamespace = process.env.RUNTIME_NAMESPACE || "";
|
||||
const workloads = parseWorkloads(process.env.WORKLOADS_B64 || "");
|
||||
const healthUrl = process.env.HEALTH_URL || "";
|
||||
const slowTaskSeconds = requiredPositiveIntEnv("SLOW_TASK_SECONDS");
|
||||
const healthTimeoutMs = requiredPositiveIntEnv("HEALTH_TIMEOUT_MS");
|
||||
|
||||
const errors = [];
|
||||
const branchCommit = rev(`refs/heads/${sourceBranch}`);
|
||||
@@ -49,6 +52,10 @@ console.log(JSON.stringify({
|
||||
follower,
|
||||
source,
|
||||
evidence,
|
||||
policy: {
|
||||
slowTaskSeconds,
|
||||
healthTimeoutMs,
|
||||
},
|
||||
errors: errors.slice(0, 6),
|
||||
statusAuthority: "kubernetes-api-serviceaccount",
|
||||
parsedDownstreamCliOutput: false,
|
||||
@@ -110,47 +117,18 @@ function readReuseConfig(commit) {
|
||||
if (!commit || !sourceStageRef) return { present: false, reason: "source-commit-missing" };
|
||||
try {
|
||||
const text = execFileSync("git", [`--git-dir=${repoPath}`, "show", `${sourceStageRef}:gitops/reuse.ymal`], { encoding: "utf8", maxBuffer: 256 * 1024 });
|
||||
const services = reuseServiceIds(text);
|
||||
const parsed = parseRuntimeReuseConfig(text, { sourceCommit: commit, stageRef: sourceStageRef });
|
||||
const summary = summarizeRuntimeReuseConfig(parsed);
|
||||
return {
|
||||
present: true,
|
||||
path: "gitops/reuse.ymal",
|
||||
...summary,
|
||||
bytes: Buffer.byteLength(text, "utf8"),
|
||||
sha256: createHash("sha256").update(text).digest("hex"),
|
||||
serviceCount: services.length,
|
||||
serviceIds: services.slice(0, 12),
|
||||
runtimeReuseMentioned: /\bruntimeReuse\b/u.test(text),
|
||||
envReuseMentioned: /\benvReuse\b/u.test(text),
|
||||
sha256: summary.sha256 ?? createHash("sha256").update(text).digest("hex"),
|
||||
};
|
||||
} catch (error) {
|
||||
return { present: false, path: "gitops/reuse.ymal", reason: shortText(error?.message || String(error)) };
|
||||
}
|
||||
}
|
||||
|
||||
function reuseServiceIds(text) {
|
||||
const ids = new Set([...text.matchAll(/(?:^|\n)\s*-\s*id:\s*([A-Za-z0-9_.-]+)/gu)].map((match) => match[1]).filter(Boolean));
|
||||
const lines = text.split(/\r?\n/u);
|
||||
let inServices = false;
|
||||
let servicesIndent = 0;
|
||||
for (const line of lines) {
|
||||
const services = /^(\s*)services:\s*$/u.exec(line);
|
||||
if (services) {
|
||||
inServices = true;
|
||||
servicesIndent = services[1].length;
|
||||
continue;
|
||||
}
|
||||
if (!inServices) continue;
|
||||
const match = /^(\s*)([A-Za-z0-9_.-]+):\s*$/u.exec(line);
|
||||
if (!match) continue;
|
||||
const indent = match[1].length;
|
||||
if (indent <= servicesIndent) {
|
||||
inServices = false;
|
||||
continue;
|
||||
}
|
||||
if (indent === servicesIndent + 2) ids.add(match[2]);
|
||||
}
|
||||
return Array.from(ids);
|
||||
}
|
||||
|
||||
function gitMirrorSummary(commit) {
|
||||
const localSource = rev(`refs/heads/${sourceBranch}`);
|
||||
const githubSource = rev(`refs/mirror-stage/heads/${sourceBranch}`);
|
||||
@@ -277,9 +255,10 @@ function taskRunsSummary(list) {
|
||||
});
|
||||
const failed = rows.filter((item) => item.status === "False");
|
||||
const active = rows.filter((item) => item.status !== "True" && item.status !== "False");
|
||||
const slow = rows.filter((item) => typeof item.durationSeconds === "number" && item.durationSeconds >= 60);
|
||||
const slow = rows.filter((item) => typeof item.durationSeconds === "number" && item.durationSeconds >= slowTaskSeconds);
|
||||
return {
|
||||
count: rows.length,
|
||||
slowThresholdSeconds: slowTaskSeconds,
|
||||
failedCount: failed.length,
|
||||
activeCount: active.length,
|
||||
slowCount: slow.length,
|
||||
@@ -321,7 +300,7 @@ async function httpProbe(url) {
|
||||
const client = url.startsWith("https:") ? https : http;
|
||||
const started = Date.now();
|
||||
return await new Promise((resolve) => {
|
||||
const req = client.get(url, { timeout: 5000 }, (res) => {
|
||||
const req = client.get(url, { timeout: healthTimeoutMs }, (res) => {
|
||||
res.resume();
|
||||
res.on("end", () => resolve({ url, ok: (res.statusCode || 0) >= 200 && (res.statusCode || 0) < 300, statusCode: res.statusCode || null, elapsedMs: Date.now() - started }));
|
||||
});
|
||||
@@ -382,6 +361,13 @@ function requiredEnv(name) {
|
||||
return value;
|
||||
}
|
||||
|
||||
function requiredPositiveIntEnv(name) {
|
||||
const value = requiredEnv(name);
|
||||
const parsed = Number(value);
|
||||
if (!Number.isInteger(parsed) || parsed <= 0) fail(`${name} must be a positive integer`);
|
||||
return parsed;
|
||||
}
|
||||
|
||||
function fail(message) {
|
||||
console.error(message);
|
||||
process.exit(1);
|
||||
|
||||
Reference in New Issue
Block a user