From ca77ba1b925239b6fe2157888096f02a71f947c9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 13 Feb 2026 15:59:14 +0000 Subject: [PATCH 1/3] Initial plan From c210f396c1f060bbcdc29de869ba899ba88c5ebc Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 13 Feb 2026 16:06:43 +0000 Subject: [PATCH 2/3] Fix add_comment handler to resolve temporary IDs in item_number field Resolves temporary IDs (e.g., aw_test01) in the item_number field before validation. Previously, the handler tried to parse temporary IDs as integers with parseInt(), which returned NaN and caused validation failures. Changes: - Import loadTemporaryIdMapFromResolved and resolveRepoIssueTarget from temporary_id.cjs - Use resolveRepoIssueTarget() to resolve item_number before validation - Handle deferred case when temporary ID is not yet resolved - Add comprehensive tests for temporary ID resolution in add_comment.test.cjs Tests added: - Should resolve temporary ID in item_number field - Should defer when temporary ID is not yet resolved - Should handle temporary ID with hash prefix - Should handle invalid temporary ID format - Should replace temporary IDs in comment body All tests pass (26 tests in add_comment.test.cjs). Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/js/add_comment.cjs | 21 +++- actions/setup/js/add_comment.test.cjs | 146 ++++++++++++++++++++++++++ 2 files changed, 163 insertions(+), 4 deletions(-) diff --git a/actions/setup/js/add_comment.cjs b/actions/setup/js/add_comment.cjs index a5d6cfef068..c84e4f9ee13 100644 --- a/actions/setup/js/add_comment.cjs +++ b/actions/setup/js/add_comment.cjs @@ -7,7 +7,7 @@ const { generateFooterWithMessages } = require("./messages_footer.cjs"); const { getRepositoryUrl } = require("./get_repository_url.cjs"); -const { replaceTemporaryIdReferences } = require("./temporary_id.cjs"); +const { replaceTemporaryIdReferences, loadTemporaryIdMapFromResolved, resolveRepoIssueTarget } = require("./temporary_id.cjs"); const { getTrackerID } = require("./get_tracker_id.cjs"); const { getErrorMessage } = require("./error_helpers.cjs"); const { resolveTarget } = require("./safe_output_helpers.cjs"); @@ -351,10 +351,21 @@ async function main(config = {}) { // Check if item_number was explicitly provided in the message if (item.item_number !== undefined && item.item_number !== null) { - // Use the explicitly provided item_number - itemNumber = typeof item.item_number === "number" ? item.item_number : parseInt(String(item.item_number), 10); + // Resolve temporary IDs if present + const resolvedTarget = resolveRepoIssueTarget(item.item_number, temporaryIdMap, repoParts.owner, repoParts.repo); - if (isNaN(itemNumber) || itemNumber <= 0) { + // Check if this is an unresolved temporary ID + if (resolvedTarget.wasTemporaryId && !resolvedTarget.resolved) { + core.info(`Deferring add_comment: unresolved temporary ID (${item.item_number})`); + return { + success: false, + deferred: true, + error: resolvedTarget.errorMessage || `Unresolved temporary ID: ${item.item_number}`, + }; + } + + // Check for other resolution errors (including null resolved) + if (resolvedTarget.errorMessage || !resolvedTarget.resolved) { core.warning(`Invalid item_number specified: ${item.item_number}`); return { success: false, @@ -362,6 +373,8 @@ async function main(config = {}) { }; } + // Use the resolved issue number (safe to access because we checked above) + itemNumber = resolvedTarget.resolved.number; core.info(`Using explicitly provided item_number: #${itemNumber}`); } else { // Check if this is a discussion context diff --git a/actions/setup/js/add_comment.test.cjs b/actions/setup/js/add_comment.test.cjs index 71936283a39..e13e57dcc27 100644 --- a/actions/setup/js/add_comment.test.cjs +++ b/actions/setup/js/add_comment.test.cjs @@ -952,4 +952,150 @@ describe("add_comment", () => { expect(graphqlCallCount).toBe(1); }); }); + + describe("temporary ID resolution", () => { + it("should resolve temporary ID in item_number field", async () => { + const addCommentScript = fs.readFileSync(path.join(__dirname, "add_comment.cjs"), "utf8"); + + let capturedIssueNumber = null; + mockGithub.rest.issues.createComment = async params => { + capturedIssueNumber = params.issue_number; + return { + data: { + id: 12345, + html_url: `https://github.com/owner/repo/issues/${params.issue_number}#issuecomment-12345`, + }, + }; + }; + + const handler = await eval(`(async () => { ${addCommentScript}; return await main({}); })()`); + + const message = { + type: "add_comment", + item_number: "aw_test01", + body: "Comment on issue created with temporary ID", + }; + + // Provide resolved temporary ID + const resolvedTemporaryIds = { + aw_test01: { repo: "owner/repo", number: 42 }, + }; + + const result = await handler(message, resolvedTemporaryIds); + + expect(result.success).toBe(true); + expect(capturedIssueNumber).toBe(42); + expect(result.itemNumber).toBe(42); + }); + + it("should defer when temporary ID is not yet resolved", async () => { + const addCommentScript = fs.readFileSync(path.join(__dirname, "add_comment.cjs"), "utf8"); + + const handler = await eval(`(async () => { ${addCommentScript}; return await main({}); })()`); + + const message = { + type: "add_comment", + item_number: "aw_test99", + body: "Comment on issue with unresolved temporary ID", + }; + + // Empty resolved map - temporary ID not yet resolved + const resolvedTemporaryIds = {}; + + const result = await handler(message, resolvedTemporaryIds); + + expect(result.success).toBe(false); + expect(result.deferred).toBe(true); + expect(result.error).toContain("aw_test99"); + }); + + it("should handle temporary ID with hash prefix", async () => { + const addCommentScript = fs.readFileSync(path.join(__dirname, "add_comment.cjs"), "utf8"); + + let capturedIssueNumber = null; + mockGithub.rest.issues.createComment = async params => { + capturedIssueNumber = params.issue_number; + return { + data: { + id: 12345, + html_url: `https://github.com/owner/repo/issues/${params.issue_number}#issuecomment-12345`, + }, + }; + }; + + const handler = await eval(`(async () => { ${addCommentScript}; return await main({}); })()`); + + const message = { + type: "add_comment", + item_number: "#aw_test02", + body: "Comment with hash prefix", + }; + + // Provide resolved temporary ID + const resolvedTemporaryIds = { + aw_test02: { repo: "owner/repo", number: 100 }, + }; + + const result = await handler(message, resolvedTemporaryIds); + + expect(result.success).toBe(true); + expect(capturedIssueNumber).toBe(100); + }); + + it("should handle invalid temporary ID format", async () => { + const addCommentScript = fs.readFileSync(path.join(__dirname, "add_comment.cjs"), "utf8"); + + const handler = await eval(`(async () => { ${addCommentScript}; return await main({}); })()`); + + const message = { + type: "add_comment", + item_number: "aw_", // Invalid: too short + body: "Comment with invalid temporary ID", + }; + + const resolvedTemporaryIds = {}; + + const result = await handler(message, resolvedTemporaryIds); + + expect(result.success).toBe(false); + expect(result.error).toContain("Invalid item_number specified"); + }); + + it("should replace temporary IDs in comment body", async () => { + const addCommentScript = fs.readFileSync(path.join(__dirname, "add_comment.cjs"), "utf8"); + + let capturedBody = null; + mockGithub.rest.issues.createComment = async params => { + capturedBody = params.body; + return { + data: { + id: 12345, + html_url: `https://github.com/owner/repo/issues/${params.issue_number}#issuecomment-12345`, + }, + }; + }; + + const handler = await eval(`(async () => { ${addCommentScript}; return await main({}); })()`); + + const message = { + type: "add_comment", + item_number: 42, + body: "References: #aw_test01 and #aw_test02", + }; + + // Provide resolved temporary IDs + const resolvedTemporaryIds = { + aw_test01: { repo: "owner/repo", number: 100 }, + aw_test02: { repo: "owner/repo", number: 200 }, + }; + + const result = await handler(message, resolvedTemporaryIds); + + expect(result.success).toBe(true); + expect(capturedBody).toContain("#100"); + expect(capturedBody).toContain("#200"); + expect(capturedBody).not.toContain("aw_test01"); + expect(capturedBody).not.toContain("aw_test02"); + }); + }); }); From 40f3831117b90aa953b5262d847723a9387262d3 Mon Sep 17 00:00:00 2001 From: Codex Date: Fri, 13 Feb 2026 16:36:57 +0000 Subject: [PATCH 3/3] Add changeset [skip-ci] --- .changeset/patch-resolve-add-comment-temp-id.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/patch-resolve-add-comment-temp-id.md diff --git a/.changeset/patch-resolve-add-comment-temp-id.md b/.changeset/patch-resolve-add-comment-temp-id.md new file mode 100644 index 00000000000..043b6bf2053 --- /dev/null +++ b/.changeset/patch-resolve-add-comment-temp-id.md @@ -0,0 +1,5 @@ +--- +"gh-aw": patch +--- + +Fix the `add_comment` safe output handler so it resolves temporary item IDs before validating the issue number.