diff --git a/actions/setup/js/ai_credits_context.cjs b/actions/setup/js/ai_credits_context.cjs index 54253052843..ac5eb7b4186 100644 --- a/actions/setup/js/ai_credits_context.cjs +++ b/actions/setup/js/ai_credits_context.cjs @@ -254,6 +254,24 @@ function parseMaxAICreditsExceededFromAuditLog(auditJsonlPathOverride) { ); } +/** + * @param {unknown} entry + * @returns {boolean} + */ +function parseUnknownModelAICreditsFromAuditEntry(entry) { + if (!entry || typeof entry !== "object") return false; + const stack = [entry]; + while (stack.length > 0) { + const node = stack.pop(); + if (!node || typeof node !== "object") continue; + for (const [, value] of Object.entries(node)) { + if (value === UNKNOWN_MODEL_AI_CREDITS_TYPE) return true; + if (value && typeof value === "object") stack.push(value); + } + } + return false; +} + /** * Detects an `unknown_model_ai_credits` error from the firewall audit log. * This HTTP 400 error is emitted by the AWF API proxy when `maxAiCredits` is active and @@ -268,20 +286,7 @@ function parseUnknownModelAICreditsFromAuditLog(auditJsonlPathOverride) { auditJsonlPathOverride, false, content => content.includes(UNKNOWN_MODEL_AI_CREDITS_TYPE), - (acc, entry) => { - if (acc) return true; - if (!entry || typeof entry !== "object") return false; - const stack = [entry]; - while (stack.length > 0) { - const node = stack.pop(); - if (!node || typeof node !== "object") continue; - for (const [, value] of Object.entries(node)) { - if (value === UNKNOWN_MODEL_AI_CREDITS_TYPE) return true; - if (value && typeof value === "object") stack.push(value); - } - } - return false; - } + (acc, entry) => acc || parseUnknownModelAICreditsFromAuditEntry(entry) ); } diff --git a/actions/setup/js/allowed_issue_fields.cjs b/actions/setup/js/allowed_issue_fields.cjs index 7436cc36c00..54aafb1afad 100644 --- a/actions/setup/js/allowed_issue_fields.cjs +++ b/actions/setup/js/allowed_issue_fields.cjs @@ -55,7 +55,7 @@ function validateAllowedIssueFields(issueFields, allowedFields) { if (!Array.isArray(allowedFields) || allowedFields.length === 0) { return; } - const allowedFieldSet = new Set(allowedFields.map(f => f.toLowerCase())); + const allowedFieldSet = new Set(allowedFields.map(field => field.toLowerCase())); if (allowedFieldSet.has("*")) { return; } diff --git a/actions/setup/js/allowed_issue_fields.test.cjs b/actions/setup/js/allowed_issue_fields.test.cjs index 7fe9b420dd2..e2198a89310 100644 --- a/actions/setup/js/allowed_issue_fields.test.cjs +++ b/actions/setup/js/allowed_issue_fields.test.cjs @@ -107,6 +107,11 @@ describe("validateAllowedIssueFields", () => { expect(() => validateAllowedIssueFields(fields, ["title", "body"])).toThrow("ERR_VALIDATION"); }); + it("throws when a field name is an empty string", () => { + const fields = [{ name: "", value: "New Title" }]; + expect(() => validateAllowedIssueFields(fields, ["title", "body"])).toThrow("ERR_VALIDATION"); + }); + it("does not throw when allowedFields is empty (no restriction)", () => { const fields = [{ name: "milestone", value: "v1.0" }]; expect(() => validateAllowedIssueFields(fields, [])).not.toThrow();