From 5579b7f9ed7ac66100b732a77801f30923d36ce8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 18 May 2026 05:07:20 +0000 Subject: [PATCH 1/2] jsweep: clean add_comment.cjs - Extract deduplicateCaseInsensitive helper to replace two repetitive deduplication loops for allowedMentionAliases - Add 2 new tests covering case-insensitive dedup and alias ordering Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- actions/setup/js/add_comment.cjs | 34 +++++++-------- actions/setup/js/add_comment.test.cjs | 61 +++++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 18 deletions(-) diff --git a/actions/setup/js/add_comment.cjs b/actions/setup/js/add_comment.cjs index 48a550a866c..df0fa9de5aa 100644 --- a/actions/setup/js/add_comment.cjs +++ b/actions/setup/js/add_comment.cjs @@ -31,6 +31,21 @@ const { resolveInvocationContext } = require("./invocation_context_helpers.cjs") /** @type {string} Safe output type handled by this module */ const HANDLER_TYPE = "add_comment"; +/** + * Deduplicate an array of strings using case-insensitive comparison, preserving original casing and order. + * @param {string[]} aliases + * @returns {string[]} + */ +function deduplicateCaseInsensitive(aliases) { + const seen = new Set(); + return aliases.filter(alias => { + const key = alias.toLowerCase(); + if (seen.has(key)) return false; + seen.add(key); + return true; + }); +} + /** * Resolve effective event name/payload for native and forwarded contexts. * Supports: @@ -566,24 +581,7 @@ async function main(config = {}) { } } } - const allowedMentionAliases = []; - const seenAllowedMentionAliases = new Set(); - for (const alias of parentAuthors) { - const key = alias.toLowerCase(); - if (seenAllowedMentionAliases.has(key)) { - continue; - } - seenAllowedMentionAliases.add(key); - allowedMentionAliases.push(alias); - } - for (const alias of configuredMentionAliases) { - const key = alias.toLowerCase(); - if (seenAllowedMentionAliases.has(key)) { - continue; - } - seenAllowedMentionAliases.add(key); - allowedMentionAliases.push(alias); - } + const allowedMentionAliases = deduplicateCaseInsensitive([...parentAuthors, ...configuredMentionAliases]); if (allowedMentionAliases.length > 0) { core.info(`[MENTIONS] Allowing aliases in comment: ${allowedMentionAliases.join(", ")}`); diff --git a/actions/setup/js/add_comment.test.cjs b/actions/setup/js/add_comment.test.cjs index 79bdc7ae368..9d89ec8b940 100644 --- a/actions/setup/js/add_comment.test.cjs +++ b/actions/setup/js/add_comment.test.cjs @@ -2775,6 +2775,67 @@ describe("add_comment", () => { // but the key test is that the handler succeeds expect(result.isDiscussion).toBe(true); }); + + it("should deduplicate allowed aliases case-insensitively across parentAuthors and configured mentions", async () => { + const addCommentScript = fs.readFileSync(path.join(__dirname, "add_comment.cjs"), "utf8"); + + // Issue author is "Alice"; configured mentions also include "alice" (different casing) + mockContext.eventName = "issues"; + mockContext.payload = { + issue: { + number: 42, + user: { login: "Alice", type: "User" }, + }, + }; + + const warnings = []; + mockCore.warning = msg => warnings.push(msg); + + let capturedBody = null; + mockGithub.rest.issues.createComment = async ({ body }) => { + capturedBody = body; + return { data: { id: 12345, html_url: "https://github.com/owner/repo/issues/42#issuecomment-12345" } }; + }; + + // configured mentions includes "alice" (lowercase dup) and "Bob" (unique) + const handler = await eval(`(async () => { ${addCommentScript}; return await main({ mentions: { allowed: ["alice", "Bob"] } }); })()`); + + const result = await handler({ type: "add_comment", body: "@Alice @Bob check this out" }, {}); + + expect(result.success).toBe(true); + // @Alice should be preserved (it's in allowedMentionAliases via parentAuthors); + // "alice" is deduplicated away (same alias, different casing) + // @Bob is preserved as unique + expect(capturedBody).toContain("@Alice"); + expect(capturedBody).toContain("@Bob"); + }); + + it("should preserve order: parentAuthors first, then configuredMentionAliases", async () => { + const addCommentScript = fs.readFileSync(path.join(__dirname, "add_comment.cjs"), "utf8"); + + mockContext.eventName = "issues"; + mockContext.payload = { + issue: { + number: 42, + user: { login: "Charlie", type: "User" }, + }, + }; + + let capturedBody = null; + mockGithub.rest.issues.createComment = async ({ body }) => { + capturedBody = body; + return { data: { id: 12345, html_url: "https://github.com/owner/repo/issues/42#issuecomment-12345" } }; + }; + + const handler = await eval(`(async () => { ${addCommentScript}; return await main({ mentions: { allowed: ["Dave", "Eve"] } }); })()`); + + const result = await handler({ type: "add_comment", body: "@Charlie @Dave @Eve thanks!" }, {}); + + expect(result.success).toBe(true); + expect(capturedBody).toContain("@Charlie"); + expect(capturedBody).toContain("@Dave"); + expect(capturedBody).toContain("@Eve"); + }); }); describe("staged mode", () => { From fc28feb1d96e25c9b0a0905a363cd810c3acd1a4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 18 May 2026 13:03:56 +0000 Subject: [PATCH 2/2] test: assert alias allowlist logs for dedupe/order Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/js/add_comment.test.cjs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/actions/setup/js/add_comment.test.cjs b/actions/setup/js/add_comment.test.cjs index 9d89ec8b940..cb4d5a01f25 100644 --- a/actions/setup/js/add_comment.test.cjs +++ b/actions/setup/js/add_comment.test.cjs @@ -2788,8 +2788,8 @@ describe("add_comment", () => { }, }; - const warnings = []; - mockCore.warning = msg => warnings.push(msg); + const infoMessages = []; + mockCore.info = msg => infoMessages.push(msg); let capturedBody = null; mockGithub.rest.issues.createComment = async ({ body }) => { @@ -2803,11 +2803,9 @@ describe("add_comment", () => { const result = await handler({ type: "add_comment", body: "@Alice @Bob check this out" }, {}); expect(result.success).toBe(true); - // @Alice should be preserved (it's in allowedMentionAliases via parentAuthors); - // "alice" is deduplicated away (same alias, different casing) - // @Bob is preserved as unique expect(capturedBody).toContain("@Alice"); expect(capturedBody).toContain("@Bob"); + expect(infoMessages).toContain("[MENTIONS] Allowing aliases in comment: Alice, Bob"); }); it("should preserve order: parentAuthors first, then configuredMentionAliases", async () => { @@ -2821,6 +2819,9 @@ describe("add_comment", () => { }, }; + const infoMessages = []; + mockCore.info = msg => infoMessages.push(msg); + let capturedBody = null; mockGithub.rest.issues.createComment = async ({ body }) => { capturedBody = body; @@ -2835,6 +2836,7 @@ describe("add_comment", () => { expect(capturedBody).toContain("@Charlie"); expect(capturedBody).toContain("@Dave"); expect(capturedBody).toContain("@Eve"); + expect(infoMessages).toContain("[MENTIONS] Allowing aliases in comment: Charlie, Dave, Eve"); }); });