fix(cicd): preserve taskrun drilldown read errors

This commit is contained in:
Codex
2026-07-03 23:38:45 +00:00
parent 7004f8f7ab
commit 41a5315168
+41 -8
View File
@@ -15,6 +15,17 @@ const useServiceAccount = Boolean(process.env.KUBERNETES_SERVICE_HOST && process
&& existsSync("/var/run/secrets/kubernetes.io/serviceaccount/token")
&& existsSync("/var/run/secrets/kubernetes.io/serviceaccount/ca.crt");
class KubeReadError extends Error {
constructor(reason, message, details = {}) {
super(shortText(message) || reason);
this.name = "KubeReadError";
this.reason = reason;
this.statusCode = details.statusCode ?? null;
this.notFound = details.notFound === true;
this.path = details.path || null;
}
}
main().catch((error) => {
process.stderr.write(error?.message || String(error));
process.exit(1);
@@ -218,21 +229,32 @@ async function readPodLog(podName, container, tailLines, limitBytes) {
}
async function getJson(path, required) {
let text = "";
try {
text = await getText(path, required);
} catch (error) {
if (!required && isNotFoundError(error)) return null;
throw error;
}
try {
const text = await getText(path, required);
return JSON.parse(text);
} catch (error) {
if (required) throw error;
return null;
throw new KubeReadError("invalid-json", `kube api returned non-JSON for ${path}: ${error?.message || String(error)}`, { path });
}
}
async function getText(path, required) {
if (useServiceAccount) return kubeApiGet(path, required);
const result = spawnSync("kubectl", ["get", "--raw", path], { encoding: "utf8", maxBuffer: Math.max(maxLogBytes * 2, 1024 * 1024) });
if (result.error) {
throw new KubeReadError("transport-error", `kubectl get --raw transport error for ${path}: ${result.error.message}`, { path });
}
if (result.status === 0) return result.stdout;
if (!required && /not found|404|NotFound/u.test(result.stderr || result.stdout)) return "";
throw new Error(shortText(result.stderr || result.stdout || `kubectl get --raw failed with exit ${result.status}`));
const body = result.stderr || result.stdout || `kubectl get --raw failed with exit ${result.status}`;
throw new KubeReadError(isNotFoundText(body) ? "not-found" : "kube-api-error", `kubectl get --raw failed for ${path}: ${body}`, {
path,
notFound: isNotFoundText(body),
});
}
function kubeApiGet(path, required) {
@@ -248,15 +270,26 @@ function kubeApiGet(path, required) {
res.on("end", () => {
const code = res.statusCode || 0;
if (code >= 200 && code < 300) resolve(body);
else if (!required && code === 404) resolve("");
else reject(new Error(shortText(body || `kube api status ${code}`)));
else reject(new KubeReadError(code === 404 || isNotFoundText(body) ? "not-found" : "kube-api-error", `kube api GET ${path} status ${code}: ${body || "-"}`, {
path,
statusCode: code,
notFound: code === 404 || isNotFoundText(body),
}));
});
});
req.on("error", reject);
req.on("error", (error) => reject(new KubeReadError("transport-error", `kube api GET ${path} transport error: ${error?.message || String(error)}`, { path })));
req.end();
});
}
function isNotFoundError(error) {
return error instanceof KubeReadError && error.notFound === true;
}
function isNotFoundText(value) {
return /\b404\b|not found|NotFound/u.test(String(value || ""));
}
function compactTerminated(value) {
if (!value) return null;
return {