diff --git a/actions/setup/js/add_comment.cjs b/actions/setup/js/add_comment.cjs index fa7ec5d7521..af4d1ad15a0 100644 --- a/actions/setup/js/add_comment.cjs +++ b/actions/setup/js/add_comment.cjs @@ -30,6 +30,9 @@ const { resolveInvocationContext } = require("./invocation_context_helpers.cjs") /** @type {string} Safe output type handled by this module */ const HANDLER_TYPE = "add_comment"; +// Keep the full list of accepted explicit wildcard target fields (including aliases +// pre-handled by resolveSafeOutputIssueTarget) to preserve a defensive boundary check. +const WILDCARD_TARGET_FIELDS = ["item_number", "issue_number", "pull_request_number", "pr_number", "pr", "pull_number"]; /** * Deduplicate an array of strings using case-insensitive comparison, preserving original casing and order. @@ -504,6 +507,16 @@ async function main(config = {}) { if (!targetResult.success) { if (targetResult.shouldFail) { + const hasExplicitWildcardTargetField = WILDCARD_TARGET_FIELDS.some(field => message[field] != null); + const missingWildcardTarget = commentTarget === "*" && !hasExplicitWildcardTargetField; + if (missingWildcardTarget) { + core.info(targetResult.error); + return { + success: false, + skipped: true, + error: targetResult.error, + }; + } core.warning(targetResult.error); return { success: false, diff --git a/actions/setup/js/add_comment.test.cjs b/actions/setup/js/add_comment.test.cjs index c09422d47fc..22b4aa7419c 100644 --- a/actions/setup/js/add_comment.test.cjs +++ b/actions/setup/js/add_comment.test.cjs @@ -222,7 +222,7 @@ describe("add_comment", () => { expect(result.itemNumber).toBe(28912); }); - it("should fail when target is '*' but no item_number provided", async () => { + it("should skip (not fail) when target is '*' but no item_number provided", async () => { const addCommentScript = fs.readFileSync(path.join(__dirname, "add_comment.cjs"), "utf8"); const handler = await eval(`(async () => { ${addCommentScript}; return await main({ target: '*' }); })()`); @@ -235,9 +235,28 @@ describe("add_comment", () => { const result = await handler(message, {}); expect(result.success).toBe(false); + expect(result.skipped).toBe(true); expect(result.error).toMatch(/no.*item_number/i); }); + it("should hard-fail (not skip) when target is '*' and explicit pull_request_number is invalid", async () => { + const addCommentScript = fs.readFileSync(path.join(__dirname, "add_comment.cjs"), "utf8"); + + const handler = await eval(`(async () => { ${addCommentScript}; return await main({ target: '*' }); })()`); + + const message = { + type: "add_comment", + pull_request_number: "invalid", + body: "Test comment with invalid explicit pull_request_number", + }; + + const result = await handler(message, {}); + + expect(result.success).toBe(false); + expect(result.skipped).toBeUndefined(); + expect(result.error).toBeTruthy(); + }); + it("should use explicit item_number even with triggering target", async () => { const addCommentScript = fs.readFileSync(path.join(__dirname, "add_comment.cjs"), "utf8");