fix(cicd): preserve taskrun drilldown read errors
This commit is contained in:
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user