cicd branch follower native closeout
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
import { readFileSync } from "node:fs";
|
||||
import https from "node:https";
|
||||
|
||||
const namespace = process.argv[2] || "";
|
||||
const pipelineRun = process.argv[3] || "";
|
||||
const host = process.env.KUBERNETES_SERVICE_HOST;
|
||||
const port = Number(process.env.KUBERNETES_SERVICE_PORT || "443");
|
||||
const token = readFileSync("/var/run/secrets/kubernetes.io/serviceaccount/token", "utf8").trim();
|
||||
const ca = readFileSync("/var/run/secrets/kubernetes.io/serviceaccount/ca.crt");
|
||||
|
||||
function request(path) {
|
||||
return new Promise((resolve) => {
|
||||
const req = https.request({ host, port, path, method: "GET", ca, headers: { authorization: `Bearer ${token}` } }, (res) => {
|
||||
let body = "";
|
||||
res.setEncoding("utf8");
|
||||
res.on("data", (chunk) => { body += chunk; });
|
||||
res.on("end", () => resolve({ status: res.statusCode || 0, body }));
|
||||
});
|
||||
req.on("error", (error) => resolve({ status: 599, body: error?.message || String(error) }));
|
||||
req.end();
|
||||
});
|
||||
}
|
||||
|
||||
function parse(text) {
|
||||
try {
|
||||
return text ? JSON.parse(text) : null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function strings(value) {
|
||||
return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
|
||||
}
|
||||
|
||||
const out = {
|
||||
ok: false,
|
||||
pipelineRun,
|
||||
pods: [],
|
||||
eventFound: false,
|
||||
degradedReason: "plan-artifacts-log-query-skipped",
|
||||
statusAuthority: "kubernetes-api-serviceaccount",
|
||||
};
|
||||
|
||||
if (!namespace || !pipelineRun) {
|
||||
process.stdout.write(JSON.stringify(out));
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
const selector = encodeURIComponent(`tekton.dev/pipelineRun=${pipelineRun}`);
|
||||
const podsResult = await request(`/api/v1/namespaces/${encodeURIComponent(namespace)}/pods?labelSelector=${selector}`);
|
||||
const pods = parse(podsResult.body);
|
||||
const items = Array.isArray(pods?.items) ? pods.items : [];
|
||||
const planPods = items.filter((pod) => {
|
||||
const labels = pod?.metadata?.labels || {};
|
||||
const name = pod?.metadata?.name || "";
|
||||
return labels["tekton.dev/pipelineTask"] === "plan-artifacts" || labels["tekton.dev/task"] === "plan-artifacts" || /plan-artifacts/u.test(name);
|
||||
});
|
||||
out.pods = planPods.map((pod) => pod?.metadata?.name).filter(Boolean);
|
||||
|
||||
const events = [];
|
||||
for (const podName of out.pods.slice(-4)) {
|
||||
const log = await request(`/api/v1/namespaces/${encodeURIComponent(namespace)}/pods/${encodeURIComponent(podName)}/log?tailLines=240`);
|
||||
if (log.status < 200 || log.status >= 300) continue;
|
||||
for (const raw of log.body.split(/\r?\n/u)) {
|
||||
const line = raw.trim();
|
||||
if (!line.startsWith("{")) continue;
|
||||
const event = parse(line);
|
||||
if (event?.event === "g14-ci-plan") events.push(event);
|
||||
}
|
||||
}
|
||||
|
||||
const latest = events.at(-1) || null;
|
||||
if (latest) {
|
||||
const audit = latest.artifactProvenanceAudit && typeof latest.artifactProvenanceAudit === "object" ? latest.artifactProvenanceAudit : null;
|
||||
const unsafeReuseServices = strings(audit?.unsafeReuseServices);
|
||||
const provenanceRebuildServices = strings(audit?.provenanceRebuildServices);
|
||||
Object.assign(out, {
|
||||
ok: true,
|
||||
eventFound: true,
|
||||
degradedReason: null,
|
||||
sourceCommitId: typeof latest.sourceCommitId === "string" ? latest.sourceCommitId : null,
|
||||
affectedServices: strings(latest.affectedServices),
|
||||
rolloutServices: strings(latest.rolloutServices),
|
||||
buildServices: strings(latest.buildServices),
|
||||
reusedServices: strings(latest.reusedServices),
|
||||
buildSkippedCount: typeof latest.buildSkippedCount === "number" ? latest.buildSkippedCount : null,
|
||||
artifactProvenanceAudit: audit,
|
||||
summary: `build=${strings(latest.buildServices).length} reuse=${strings(latest.reusedServices).length} unsafeReuse=${unsafeReuseServices.length} provenanceRebuild=${provenanceRebuildServices.length}`,
|
||||
disclosure: "parsed from plan-artifacts g14-ci-plan log event via Kubernetes pod logs",
|
||||
});
|
||||
} else {
|
||||
out.degradedReason = podsResult.status >= 200 && podsResult.status < 300 ? "g14-ci-plan-event-not-found" : "plan-artifacts-pod-list-failed";
|
||||
}
|
||||
|
||||
process.stdout.write(JSON.stringify(out));
|
||||
Reference in New Issue
Block a user