diff --git a/actions/setup/js/safe_output_handler_manager.cjs b/actions/setup/js/safe_output_handler_manager.cjs index 87e50ab6646..3bad068e9f3 100644 --- a/actions/setup/js/safe_output_handler_manager.cjs +++ b/actions/setup/js/safe_output_handler_manager.cjs @@ -1166,7 +1166,21 @@ async function processMessages(messageHandlers, messages, onItemCreated = null) // Check if this output was created with unresolved temporary IDs // For create_issue, create_discussion, add_comment - check if body has unresolved IDs - // Handle add_comment which returns an array of comments + // Handle the current add_comment result shape. + if (messageType === "add_comment" && result?.commentId && result?.repo) { + const contentToCheck = getContentToCheck(messageType, message, result); + if (contentToCheck && hasUnresolvedTemporaryIds(contentToCheck, temporaryIdMap, artifactUrlMap)) { + core.info(`Comment ${result.commentId} on ${result.repo}#${result.itemNumber} was created with unresolved temporary IDs - tracking for update`); + outputsWithUnresolvedIds.push({ + type: messageType, + message, + result, + originalTempIdMapSize: tempIdMapSizeBefore, + }); + } + } + + // Handle the legacy add_comment result shape. if (messageType === "add_comment" && Array.isArray(result)) { const contentToCheck = getContentToCheck(messageType, message, result); if (contentToCheck && hasUnresolvedTemporaryIds(contentToCheck, temporaryIdMap, artifactUrlMap)) { @@ -1177,12 +1191,7 @@ async function processMessages(messageHandlers, messages, onItemCreated = null) outputsWithUnresolvedIds.push({ type: messageType, message: message, - result: { - commentId: comment._tracking.commentId, - itemNumber: comment._tracking.itemNumber, - repo: comment._tracking.repo, - isDiscussion: comment._tracking.isDiscussion, - }, + result: { ...comment._tracking, ...(comment.body ? { body: comment.body } : {}) }, originalTempIdMapSize: tempIdMapSizeBefore, }); } @@ -1384,7 +1393,7 @@ function getContentToCheck(messageType, message, result) { case "create_discussion": return message.body || ""; case "add_comment": - return message.body || ""; + return result?.body || message.body || ""; case "comment_memory": return result?.managedBody || message.body || ""; case "create_pull_request": @@ -2026,4 +2035,5 @@ module.exports = { partitionFailureResults, computeSafeOutputsStatus, setSafeOutputsStatusOutputs, + processSyntheticUpdates, }; diff --git a/actions/setup/js/safe_output_handler_manager.test.cjs b/actions/setup/js/safe_output_handler_manager.test.cjs index 7ebef3c5da2..95e5e9a40d3 100644 --- a/actions/setup/js/safe_output_handler_manager.test.cjs +++ b/actions/setup/js/safe_output_handler_manager.test.cjs @@ -21,6 +21,7 @@ import { partitionFailureResults, computeSafeOutputsStatus, setSafeOutputsStatusOutputs, + processSyntheticUpdates, } from "./safe_output_handler_manager.cjs"; const require = createRequire(import.meta.url); @@ -153,6 +154,88 @@ describe("Safe Output Handler Manager", () => { expect(sortMessageIndicesByTemporaryIdDependencies([dependent, producer, unrelated])).toEqual([1, 0, 2]); }); + + it("tracks a comment emitted before its temporary-ID producer", async () => { + const callOrder = []; + const handlers = new Map([ + [ + "add_comment", + vi.fn(async (_message, resolvedTemporaryIds) => { + callOrder.push("add_comment"); + expect(resolvedTemporaryIds).toEqual({}); + return { + success: true, + commentId: 123, + itemNumber: 42, + repo: "owner/repo", + isDiscussion: false, + body: "Tracking issue: #aw_track1\n\nHandler footer marker", + }; + }), + ], + [ + "create_issue", + vi.fn(async () => { + callOrder.push("create_issue"); + return { success: true, temporaryId: "aw_track1", repo: "owner/tracker", number: 99 }; + }), + ], + ]); + const messages = [ + { type: "add_comment", item_number: 42, body: "Tracking issue: #aw_track1" }, + { type: "create_issue", temporary_id: "aw_track1", title: "Tracking issue" }, + ]; + + const result = await processMessages(handlers, messages); + + expect(callOrder).toEqual(["add_comment", "create_issue"]); + expect(result.temporaryIdMap.aw_track1).toEqual({ repo: "owner/tracker", number: 99 }); + expect(result.outputsWithUnresolvedIds).toEqual([ + { + type: "add_comment", + message: { type: "add_comment", item_number: 42, body: "Tracking issue: #aw_track1" }, + result: { + success: true, + commentId: 123, + itemNumber: 42, + repo: "owner/repo", + isDiscussion: false, + body: "Tracking issue: #aw_track1\n\nHandler footer marker", + }, + originalTempIdMapSize: 0, + }, + ]); + }); + + it("updates the posted comment body while retaining handler metadata", async () => { + const updateComment = vi.fn().mockResolvedValue({}); + const github = { rest: { issues: { updateComment } } }; + const trackedOutputs = [ + { + type: "add_comment", + message: { type: "add_comment", body: "Tracking issue: #aw_track1" }, + result: { + success: true, + commentId: 123, + itemNumber: 42, + repo: "owner/repo", + isDiscussion: false, + body: "Tracking issue: #aw_track1\n\nHandler footer marker", + }, + originalTempIdMapSize: 0, + }, + ]; + + const updateCount = await processSyntheticUpdates(github, {}, trackedOutputs, new Map([["aw_track1", { repo: "owner/tracker", number: 99 }]]), new Map()); + + expect(updateCount).toBe(1); + expect(updateComment).toHaveBeenCalledWith({ + owner: "owner", + repo: "repo", + comment_id: 123, + body: "Tracking issue: owner/tracker#99\n\nHandler footer marker", + }); + }); }); describe("logCreatedItemFromResult", () => {