From 8fde14d81df0f26ece7d8d216de53d348b9f274e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Oct 2025 04:03:55 +0000 Subject: [PATCH 1/5] Initial plan From 766bdac8f0545d89ce78ea99ed3a0d9d80cc815b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Oct 2025 04:12:29 +0000 Subject: [PATCH 2/5] Remove shouldEditComment = true for non-command workflows Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .../js/add_reaction_and_edit_comment.cjs | 6 -- .../js/add_reaction_and_edit_comment.test.cjs | 81 +++++++------------ 2 files changed, 31 insertions(+), 56 deletions(-) diff --git a/pkg/workflow/js/add_reaction_and_edit_comment.cjs b/pkg/workflow/js/add_reaction_and_edit_comment.cjs index 0fd124df012..86fbdc8ae58 100644 --- a/pkg/workflow/js/add_reaction_and_edit_comment.cjs +++ b/pkg/workflow/js/add_reaction_and_edit_comment.cjs @@ -38,8 +38,6 @@ async function main() { } reactionEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/comments`; - // Create a comment for issue events - shouldEditComment = true; break; case "issue_comment": @@ -63,8 +61,6 @@ async function main() { // PRs are "issues" for the reactions endpoint reactionEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/comments`; - // Create a comment for pull request events - shouldEditComment = true; break; case "pull_request_review_comment": @@ -89,8 +85,6 @@ async function main() { const discussion = await getDiscussionId(owner, repo, discussionNumber); reactionEndpoint = discussion.id; // Store node ID for GraphQL commentUpdateEndpoint = `discussion:${discussionNumber}`; // Special format to indicate discussion - // Create a comment for discussion events - shouldEditComment = true; break; case "discussion_comment": diff --git a/pkg/workflow/js/add_reaction_and_edit_comment.test.cjs b/pkg/workflow/js/add_reaction_and_edit_comment.test.cjs index 50d19f0ef96..97c3a2b0c1c 100644 --- a/pkg/workflow/js/add_reaction_and_edit_comment.test.cjs +++ b/pkg/workflow/js/add_reaction_and_edit_comment.test.cjs @@ -139,8 +139,9 @@ describe("add_reaction_and_edit_comment.cjs", () => { }); describe("Pull request reactions", () => { - it("should add reaction to pull request successfully", async () => { + it("should add reaction to pull request successfully (no comment)", async () => { process.env.GITHUB_AW_REACTION = "heart"; + // NO GITHUB_AW_COMMAND set - this is NOT a command workflow global.context.eventName = "pull_request"; global.context.payload = { pull_request: { number: 456 }, @@ -162,7 +163,11 @@ describe("add_reaction_and_edit_comment.cjs", () => { }) ); + // Verify only 1 call was made (reaction, no comment) + expect(mockGithub.request).toHaveBeenCalledTimes(1); + expect(mockCore.setOutput).toHaveBeenCalledWith("reaction-id", "789"); + expect(mockCore.setOutput).not.toHaveBeenCalledWith("comment-id", expect.anything()); }); }); @@ -331,40 +336,38 @@ describe("add_reaction_and_edit_comment.cjs", () => { }); describe("Comment creation (always creates new comments)", () => { - it("should create new comment for issue event", async () => { + it("should NOT create comment for issue event (non-command workflow)", async () => { process.env.GITHUB_AW_REACTION = "eyes"; process.env.GITHUB_AW_WORKFLOW_NAME = "Test Workflow"; + // NO GITHUB_AW_COMMAND set - this is NOT a command workflow global.context.eventName = "issues"; global.context.payload = { issue: { number: 123 }, repository: { html_url: "https://github.com/testowner/testrepo" }, }; - // Mock reaction call - mockGithub.request - .mockResolvedValueOnce({ - data: { id: 456 }, - }) - // Mock comment creation - .mockResolvedValueOnce({ - data: { id: 789, html_url: "https://github.com/testowner/testrepo/issues/123#issuecomment-789" }, - }); + // Mock reaction call only (no comment creation) + mockGithub.request.mockResolvedValueOnce({ + data: { id: 456 }, + }); // Execute the script await eval(`(async () => { ${reactionScript} })()`); - // Verify comment was created (not edited) + // Verify reaction was added expect(mockGithub.request).toHaveBeenCalledWith( - "POST /repos/testowner/testrepo/issues/123/comments", + "POST /repos/testowner/testrepo/issues/123/reactions", expect.objectContaining({ - body: expect.stringContaining("Agentic [Test Workflow]"), + content: "eyes", }) ); - // Verify outputs - expect(mockCore.setOutput).toHaveBeenCalledWith("comment-id", "789"); - expect(mockCore.setOutput).toHaveBeenCalledWith("comment-url", "https://github.com/testowner/testrepo/issues/123#issuecomment-789"); - expect(mockCore.setOutput).toHaveBeenCalledWith("comment-repo", "testowner/testrepo"); + // Verify comment was NOT created (only 1 call for reaction) + expect(mockGithub.request).toHaveBeenCalledTimes(1); + + // Verify only reaction output was set, not comment outputs + expect(mockCore.setOutput).toHaveBeenCalledWith("reaction-id", "456"); + expect(mockCore.setOutput).not.toHaveBeenCalledWith("comment-id", expect.anything()); }); it("should create new comment for issue_comment event (not edit)", async () => { @@ -450,9 +453,10 @@ describe("add_reaction_and_edit_comment.cjs", () => { expect(mockCore.setOutput).toHaveBeenCalledWith("comment-repo", "testowner/testrepo"); }); - it("should create comment on discussion when shouldEditComment is true", async () => { + it("should NOT create comment on discussion (non-command workflow)", async () => { process.env.GITHUB_AW_REACTION = "eyes"; process.env.GITHUB_AW_WORKFLOW_NAME = "Test Workflow"; + // NO GITHUB_AW_COMMAND set - this is NOT a command workflow global.context.eventName = "discussion"; global.context.payload = { discussion: { number: 10 }, @@ -477,43 +481,20 @@ describe("add_reaction_and_edit_comment.cjs", () => { content: "EYES", }, }, - }) - // Mock GraphQL query to get discussion ID again for comment - .mockResolvedValueOnce({ - repository: { - discussion: { - id: "D_kwDOABcD1M4AaBbC", - }, - }, - }) - // Mock GraphQL mutation to add comment - .mockResolvedValueOnce({ - addDiscussionComment: { - comment: { - id: "DC_kwDOABcD1M4AaBbD", - url: "https://github.com/testowner/testrepo/discussions/10#discussioncomment-456", - }, - }, }); // Execute the script await eval(`(async () => { ${reactionScript} })()`); - // Verify comment was created - expect(mockGithub.graphql).toHaveBeenCalledWith( - expect.stringContaining("addDiscussionComment"), - expect.objectContaining({ - dId: "D_kwDOABcD1M4AaBbC", - body: expect.stringContaining("Agentic [Test Workflow]"), - }) - ); + // Verify reaction was added (2 GraphQL calls: get discussion ID + add reaction) + expect(mockGithub.graphql).toHaveBeenCalledTimes(2); - expect(mockCore.setOutput).toHaveBeenCalledWith("comment-id", "DC_kwDOABcD1M4AaBbD"); - expect(mockCore.setOutput).toHaveBeenCalledWith( - "comment-url", - "https://github.com/testowner/testrepo/discussions/10#discussioncomment-456" - ); - expect(mockCore.setOutput).toHaveBeenCalledWith("comment-repo", "testowner/testrepo"); + // Verify comment was NOT created (no addDiscussionComment mutation) + expect(mockGithub.graphql).not.toHaveBeenCalledWith(expect.stringContaining("addDiscussionComment"), expect.anything()); + + // Verify only reaction output was set + expect(mockCore.setOutput).toHaveBeenCalledWith("reaction-id", "MDg6UmVhY3Rpb24xMjM0NTY3ODk="); + expect(mockCore.setOutput).not.toHaveBeenCalledWith("comment-id", expect.anything()); }); it("should create new comment for discussion_comment events", async () => { From 5b1a2ea9785e5540864739e99630d1e1ebb889f8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Oct 2025 04:32:38 +0000 Subject: [PATCH 3/5] Remove comment editing functionality entirely Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .github/workflows/brave.lock.yml | 3 - .../workflows/changeset-generator.lock.yml | 3 - .github/workflows/dev.lock.yml | 3 - .github/workflows/issue-classifier.lock.yml | 3 - .github/workflows/pdf-summary.lock.yml | 3 - .github/workflows/plan.lock.yml | 3 - .github/workflows/poem-bot.lock.yml | 3 - .github/workflows/q.lock.yml | 3 - .github/workflows/scout.lock.yml | 3 - .github/workflows/tidy.lock.yml | 3 - .github/workflows/unbloat-docs.lock.yml | 3 - .../js/add_reaction_and_edit_comment.cjs | 214 +--------------- .../js/add_reaction_and_edit_comment.test.cjs | 233 +----------------- 13 files changed, 4 insertions(+), 476 deletions(-) diff --git a/.github/workflows/brave.lock.yml b/.github/workflows/brave.lock.yml index fe7ad65d4e9..07cf491a22e 100644 --- a/.github/workflows/brave.lock.yml +++ b/.github/workflows/brave.lock.yml @@ -370,7 +370,6 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/comments`; - shouldEditComment = true; break; case "issue_comment": const commentId = context.payload?.comment?.id; @@ -390,7 +389,6 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/comments`; - shouldEditComment = true; break; case "pull_request_review_comment": const reviewCommentId = context.payload?.comment?.id; @@ -411,7 +409,6 @@ jobs: const discussion = await getDiscussionId(owner, repo, discussionNumber); reactionEndpoint = discussion.id; commentUpdateEndpoint = `discussion:${discussionNumber}`; - shouldEditComment = true; break; case "discussion_comment": const discussionCommentNumber = context.payload?.discussion?.number; diff --git a/.github/workflows/changeset-generator.lock.yml b/.github/workflows/changeset-generator.lock.yml index 973e233aaaf..1fc42b874df 100644 --- a/.github/workflows/changeset-generator.lock.yml +++ b/.github/workflows/changeset-generator.lock.yml @@ -362,7 +362,6 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/comments`; - shouldEditComment = true; break; case "issue_comment": const commentId = context.payload?.comment?.id; @@ -382,7 +381,6 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/comments`; - shouldEditComment = true; break; case "pull_request_review_comment": const reviewCommentId = context.payload?.comment?.id; @@ -403,7 +401,6 @@ jobs: const discussion = await getDiscussionId(owner, repo, discussionNumber); reactionEndpoint = discussion.id; commentUpdateEndpoint = `discussion:${discussionNumber}`; - shouldEditComment = true; break; case "discussion_comment": const discussionCommentNumber = context.payload?.discussion?.number; diff --git a/.github/workflows/dev.lock.yml b/.github/workflows/dev.lock.yml index ec00dee3eff..9da03219885 100644 --- a/.github/workflows/dev.lock.yml +++ b/.github/workflows/dev.lock.yml @@ -282,7 +282,6 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/comments`; - shouldEditComment = true; break; case "issue_comment": const commentId = context.payload?.comment?.id; @@ -302,7 +301,6 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/comments`; - shouldEditComment = true; break; case "pull_request_review_comment": const reviewCommentId = context.payload?.comment?.id; @@ -323,7 +321,6 @@ jobs: const discussion = await getDiscussionId(owner, repo, discussionNumber); reactionEndpoint = discussion.id; commentUpdateEndpoint = `discussion:${discussionNumber}`; - shouldEditComment = true; break; case "discussion_comment": const discussionCommentNumber = context.payload?.discussion?.number; diff --git a/.github/workflows/issue-classifier.lock.yml b/.github/workflows/issue-classifier.lock.yml index aecbb1d663f..12fcab24804 100644 --- a/.github/workflows/issue-classifier.lock.yml +++ b/.github/workflows/issue-classifier.lock.yml @@ -359,7 +359,6 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/comments`; - shouldEditComment = true; break; case "issue_comment": const commentId = context.payload?.comment?.id; @@ -379,7 +378,6 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/comments`; - shouldEditComment = true; break; case "pull_request_review_comment": const reviewCommentId = context.payload?.comment?.id; @@ -400,7 +398,6 @@ jobs: const discussion = await getDiscussionId(owner, repo, discussionNumber); reactionEndpoint = discussion.id; commentUpdateEndpoint = `discussion:${discussionNumber}`; - shouldEditComment = true; break; case "discussion_comment": const discussionCommentNumber = context.payload?.discussion?.number; diff --git a/.github/workflows/pdf-summary.lock.yml b/.github/workflows/pdf-summary.lock.yml index 5e51b548e1f..fd62cd0b2aa 100644 --- a/.github/workflows/pdf-summary.lock.yml +++ b/.github/workflows/pdf-summary.lock.yml @@ -391,7 +391,6 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/comments`; - shouldEditComment = true; break; case "issue_comment": const commentId = context.payload?.comment?.id; @@ -411,7 +410,6 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/comments`; - shouldEditComment = true; break; case "pull_request_review_comment": const reviewCommentId = context.payload?.comment?.id; @@ -432,7 +430,6 @@ jobs: const discussion = await getDiscussionId(owner, repo, discussionNumber); reactionEndpoint = discussion.id; commentUpdateEndpoint = `discussion:${discussionNumber}`; - shouldEditComment = true; break; case "discussion_comment": const discussionCommentNumber = context.payload?.discussion?.number; diff --git a/.github/workflows/plan.lock.yml b/.github/workflows/plan.lock.yml index 91b66b56ff3..e99ac36d730 100644 --- a/.github/workflows/plan.lock.yml +++ b/.github/workflows/plan.lock.yml @@ -361,7 +361,6 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/comments`; - shouldEditComment = true; break; case "issue_comment": const commentId = context.payload?.comment?.id; @@ -381,7 +380,6 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/comments`; - shouldEditComment = true; break; case "pull_request_review_comment": const reviewCommentId = context.payload?.comment?.id; @@ -402,7 +400,6 @@ jobs: const discussion = await getDiscussionId(owner, repo, discussionNumber); reactionEndpoint = discussion.id; commentUpdateEndpoint = `discussion:${discussionNumber}`; - shouldEditComment = true; break; case "discussion_comment": const discussionCommentNumber = context.payload?.discussion?.number; diff --git a/.github/workflows/poem-bot.lock.yml b/.github/workflows/poem-bot.lock.yml index cfba46ec886..a6d6b9f85a7 100644 --- a/.github/workflows/poem-bot.lock.yml +++ b/.github/workflows/poem-bot.lock.yml @@ -402,7 +402,6 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/comments`; - shouldEditComment = true; break; case "issue_comment": const commentId = context.payload?.comment?.id; @@ -422,7 +421,6 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/comments`; - shouldEditComment = true; break; case "pull_request_review_comment": const reviewCommentId = context.payload?.comment?.id; @@ -443,7 +441,6 @@ jobs: const discussion = await getDiscussionId(owner, repo, discussionNumber); reactionEndpoint = discussion.id; commentUpdateEndpoint = `discussion:${discussionNumber}`; - shouldEditComment = true; break; case "discussion_comment": const discussionCommentNumber = context.payload?.discussion?.number; diff --git a/.github/workflows/q.lock.yml b/.github/workflows/q.lock.yml index f80c3c03cac..41f424c3e0a 100644 --- a/.github/workflows/q.lock.yml +++ b/.github/workflows/q.lock.yml @@ -413,7 +413,6 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/comments`; - shouldEditComment = true; break; case "issue_comment": const commentId = context.payload?.comment?.id; @@ -433,7 +432,6 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/comments`; - shouldEditComment = true; break; case "pull_request_review_comment": const reviewCommentId = context.payload?.comment?.id; @@ -454,7 +452,6 @@ jobs: const discussion = await getDiscussionId(owner, repo, discussionNumber); reactionEndpoint = discussion.id; commentUpdateEndpoint = `discussion:${discussionNumber}`; - shouldEditComment = true; break; case "discussion_comment": const discussionCommentNumber = context.payload?.discussion?.number; diff --git a/.github/workflows/scout.lock.yml b/.github/workflows/scout.lock.yml index dd7803feb7b..5c69003ec2b 100644 --- a/.github/workflows/scout.lock.yml +++ b/.github/workflows/scout.lock.yml @@ -425,7 +425,6 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/comments`; - shouldEditComment = true; break; case "issue_comment": const commentId = context.payload?.comment?.id; @@ -445,7 +444,6 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/comments`; - shouldEditComment = true; break; case "pull_request_review_comment": const reviewCommentId = context.payload?.comment?.id; @@ -466,7 +464,6 @@ jobs: const discussion = await getDiscussionId(owner, repo, discussionNumber); reactionEndpoint = discussion.id; commentUpdateEndpoint = `discussion:${discussionNumber}`; - shouldEditComment = true; break; case "discussion_comment": const discussionCommentNumber = context.payload?.discussion?.number; diff --git a/.github/workflows/tidy.lock.yml b/.github/workflows/tidy.lock.yml index 84fb4aff849..80b7f27b0cc 100644 --- a/.github/workflows/tidy.lock.yml +++ b/.github/workflows/tidy.lock.yml @@ -212,7 +212,6 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/comments`; - shouldEditComment = true; break; case "issue_comment": const commentId = context.payload?.comment?.id; @@ -232,7 +231,6 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/comments`; - shouldEditComment = true; break; case "pull_request_review_comment": const reviewCommentId = context.payload?.comment?.id; @@ -253,7 +251,6 @@ jobs: const discussion = await getDiscussionId(owner, repo, discussionNumber); reactionEndpoint = discussion.id; commentUpdateEndpoint = `discussion:${discussionNumber}`; - shouldEditComment = true; break; case "discussion_comment": const discussionCommentNumber = context.payload?.discussion?.number; diff --git a/.github/workflows/unbloat-docs.lock.yml b/.github/workflows/unbloat-docs.lock.yml index 5d9430ff3ce..f0fd53059d5 100644 --- a/.github/workflows/unbloat-docs.lock.yml +++ b/.github/workflows/unbloat-docs.lock.yml @@ -216,7 +216,6 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/comments`; - shouldEditComment = true; break; case "issue_comment": const commentId = context.payload?.comment?.id; @@ -236,7 +235,6 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/comments`; - shouldEditComment = true; break; case "pull_request_review_comment": const reviewCommentId = context.payload?.comment?.id; @@ -257,7 +255,6 @@ jobs: const discussion = await getDiscussionId(owner, repo, discussionNumber); reactionEndpoint = discussion.id; commentUpdateEndpoint = `discussion:${discussionNumber}`; - shouldEditComment = true; break; case "discussion_comment": const discussionCommentNumber = context.payload?.discussion?.number; diff --git a/pkg/workflow/js/add_reaction_and_edit_comment.cjs b/pkg/workflow/js/add_reaction_and_edit_comment.cjs index 86fbdc8ae58..7b15ea14012 100644 --- a/pkg/workflow/js/add_reaction_and_edit_comment.cjs +++ b/pkg/workflow/js/add_reaction_and_edit_comment.cjs @@ -1,17 +1,8 @@ async function main() { // Read inputs from environment variables const reaction = process.env.GITHUB_AW_REACTION || "eyes"; - const command = process.env.GITHUB_AW_COMMAND; // Only present for command workflows - const runId = context.runId; - const githubServer = process.env.GITHUB_SERVER_URL || "https://github.com"; - const runUrl = context.payload.repository - ? `${context.payload.repository.html_url}/actions/runs/${runId}` - : `${githubServer}/${context.repo.owner}/${context.repo.repo}/actions/runs/${runId}`; core.info(`Reaction type: ${reaction}`); - core.info(`Command name: ${command || "none"}`); - core.info(`Run ID: ${runId}`); - core.info(`Run URL: ${runUrl}`); // Validate reaction type const validReactions = ["+1", "-1", "laugh", "confused", "heart", "hooray", "rocket", "eyes"]; @@ -22,8 +13,6 @@ async function main() { // Determine the API endpoint based on the event type let reactionEndpoint; - let commentUpdateEndpoint; - let shouldEditComment = false; const eventName = context.eventName; const owner = context.repo.owner; const repo = context.repo.repo; @@ -37,7 +26,6 @@ async function main() { return; } reactionEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/reactions`; - commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/comments`; break; case "issue_comment": @@ -47,9 +35,6 @@ async function main() { return; } reactionEndpoint = `/repos/${owner}/${repo}/issues/comments/${commentId}/reactions`; - commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/comments/${commentId}`; - // Only edit comments for command workflows - shouldEditComment = command ? true : false; break; case "pull_request": @@ -60,7 +45,6 @@ async function main() { } // PRs are "issues" for the reactions endpoint reactionEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/reactions`; - commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/comments`; break; case "pull_request_review_comment": @@ -70,9 +54,6 @@ async function main() { return; } reactionEndpoint = `/repos/${owner}/${repo}/pulls/comments/${reviewCommentId}/reactions`; - commentUpdateEndpoint = `/repos/${owner}/${repo}/pulls/comments/${reviewCommentId}`; - // Only edit comments for command workflows - shouldEditComment = command ? true : false; break; case "discussion": @@ -84,7 +65,6 @@ async function main() { // Discussions use GraphQL API - get the node ID const discussion = await getDiscussionId(owner, repo, discussionNumber); reactionEndpoint = discussion.id; // Store node ID for GraphQL - commentUpdateEndpoint = `discussion:${discussionNumber}`; // Special format to indicate discussion break; case "discussion_comment": @@ -101,9 +81,6 @@ async function main() { return; } reactionEndpoint = commentNodeId; // Store node ID for GraphQL - commentUpdateEndpoint = `discussion_comment:${discussionCommentNumber}:${discussionCommentId}`; // Special format - // Only edit comments for command workflows - shouldEditComment = command ? true : false; break; default: @@ -113,7 +90,7 @@ async function main() { core.info(`Reaction API endpoint: ${reactionEndpoint}`); - // Add reaction first + // Add reaction // For discussions, reactionEndpoint is a node ID (GraphQL), otherwise it's a REST API path const isDiscussionEvent = eventName === "discussion" || eventName === "discussion_comment"; if (isDiscussionEvent) { @@ -121,22 +98,10 @@ async function main() { } else { await addReaction(reactionEndpoint, reaction); } - - // Then add or edit comment if applicable - if (shouldEditComment && commentUpdateEndpoint) { - core.info(`Comment endpoint: ${commentUpdateEndpoint}`); - await addOrEditCommentWithWorkflowLink(commentUpdateEndpoint, runUrl, eventName); - } else { - if (!command && commentUpdateEndpoint) { - core.info("Skipping comment edit - only available for command workflows"); - } else { - core.info(`Skipping comment for event type: ${eventName}`); - } - } } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); - core.error(`Failed to process reaction and comment edit: ${errorMessage}`); - core.setFailed(`Failed to process reaction and comment edit: ${errorMessage}`); + core.error(`Failed to process reaction: ${errorMessage}`); + core.setFailed(`Failed to process reaction: ${errorMessage}`); } } @@ -235,177 +200,4 @@ async function getDiscussionId(owner, repo, discussionNumber) { }; } -/** - * Get the node ID for a discussion comment - * @param {string} owner - Repository owner - * @param {string} repo - Repository name - * @param {number} discussionNumber - Discussion number - * @param {number} commentId - Comment ID (database ID, not node ID) - * @returns {Promise<{id: string, url: string}>} Comment details - */ -async function getDiscussionCommentId(owner, repo, discussionNumber, commentId) { - // First, get the discussion ID - const discussion = await getDiscussionId(owner, repo, discussionNumber); - if (!discussion) throw new Error(`Discussion #${discussionNumber} not found in ${owner}/${repo}`); - - // Then fetch the comment by traversing discussion comments - // Note: GitHub's GraphQL API doesn't provide a direct way to query comment by database ID - // We need to use the comment's node ID from the event payload if available - // For now, we'll use a simplified approach - the commentId from context.payload.comment.node_id - - // If the event payload provides node_id, we can use it directly - // Otherwise, this would need to fetch all comments and find the matching one - const nodeId = context.payload?.comment?.node_id; - if (nodeId) { - return { - id: nodeId, - url: context.payload.comment?.html_url || discussion?.url, - }; - } - - throw new Error(`Discussion comment node ID not found in event payload for comment ${commentId}`); -} - -/** - * Add or edit a comment to add a workflow run link - * @param {string} endpoint - The GitHub API endpoint to update or create the comment (or special format for discussions) - * @param {string} runUrl - The URL of the workflow run - * @param {string} eventName - The event type (to determine if we create or edit) - */ -async function addOrEditCommentWithWorkflowLink(endpoint, runUrl, eventName) { - try { - // Get workflow name from environment variable - const workflowName = process.env.GITHUB_AW_WORKFLOW_NAME || "Workflow"; - - // Handle discussion events specially - if (eventName === "discussion") { - // Parse discussion number from special format: "discussion:NUMBER" - const discussionNumber = parseInt(endpoint.split(":")[1], 10); - const workflowLinkText = `Agentic [${workflowName}](${runUrl}) triggered by this discussion.`; - - // Create a new comment on the discussion using GraphQL - const { repository } = await github.graphql( - ` - query($owner: String!, $repo: String!, $num: Int!) { - repository(owner: $owner, name: $repo) { - discussion(number: $num) { - id - } - } - }`, - { owner: context.repo.owner, repo: context.repo.repo, num: discussionNumber } - ); - - const discussionId = repository.discussion.id; - - const result = await github.graphql( - ` - mutation($dId: ID!, $body: String!) { - addDiscussionComment(input: { discussionId: $dId, body: $body }) { - comment { - id - url - } - } - }`, - { dId: discussionId, body: workflowLinkText } - ); - - const comment = result.addDiscussionComment.comment; - core.info(`Successfully created discussion comment with workflow link`); - core.info(`Comment ID: ${comment.id}`); - core.info(`Comment URL: ${comment.url}`); - core.info(`Comment Repo: ${context.repo.owner}/${context.repo.repo}`); - core.setOutput("comment-id", comment.id); - core.setOutput("comment-url", comment.url); - core.setOutput("comment-repo", `${context.repo.owner}/${context.repo.repo}`); - return; - } else if (eventName === "discussion_comment") { - // Parse discussion number from special format: "discussion_comment:NUMBER:COMMENT_ID" - const discussionNumber = parseInt(endpoint.split(":")[1], 10); - const workflowLinkText = `Agentic [${workflowName}](${runUrl}) triggered by this discussion comment.`; - - // Create a new comment on the discussion using GraphQL - const { repository } = await github.graphql( - ` - query($owner: String!, $repo: String!, $num: Int!) { - repository(owner: $owner, name: $repo) { - discussion(number: $num) { - id - } - } - }`, - { owner: context.repo.owner, repo: context.repo.repo, num: discussionNumber } - ); - - const discussionId = repository.discussion.id; - - const result = await github.graphql( - ` - mutation($dId: ID!, $body: String!) { - addDiscussionComment(input: { discussionId: $dId, body: $body }) { - comment { - id - url - } - } - }`, - { dId: discussionId, body: workflowLinkText } - ); - - const comment = result.addDiscussionComment.comment; - core.info(`Successfully created discussion comment with workflow link`); - core.info(`Comment ID: ${comment.id}`); - core.info(`Comment URL: ${comment.url}`); - core.info(`Comment Repo: ${context.repo.owner}/${context.repo.repo}`); - core.setOutput("comment-id", comment.id); - core.setOutput("comment-url", comment.url); - core.setOutput("comment-repo", `${context.repo.owner}/${context.repo.repo}`); - return; - } - - // Always create a new comment (never edit existing comments) - let eventTypeDescription; - switch (eventName) { - case "issues": - eventTypeDescription = "issue"; - break; - case "pull_request": - eventTypeDescription = "pull request"; - break; - case "issue_comment": - eventTypeDescription = "issue comment"; - break; - case "pull_request_review_comment": - eventTypeDescription = "pull request review comment"; - break; - default: - eventTypeDescription = "event"; - } - - const workflowLinkText = `Agentic [${workflowName}](${runUrl}) triggered by this ${eventTypeDescription}.`; - - const createResponse = await github.request("POST " + endpoint, { - body: workflowLinkText, - headers: { - Accept: "application/vnd.github+json", - }, - }); - - core.info(`Successfully created comment with workflow link`); - core.info(`Comment ID: ${createResponse.data.id}`); - core.info(`Comment URL: ${createResponse.data.html_url}`); - core.info(`Comment Repo: ${context.repo.owner}/${context.repo.repo}`); - core.setOutput("comment-id", createResponse.data.id.toString()); - core.setOutput("comment-url", createResponse.data.html_url); - core.setOutput("comment-repo", `${context.repo.owner}/${context.repo.repo}`); - } catch (error) { - // Don't fail the entire job if comment editing/creation fails - just log it - const errorMessage = error instanceof Error ? error.message : String(error); - core.warning( - "Failed to add/edit comment with workflow link (This is not critical - the reaction was still added successfully): " + errorMessage - ); - } -} - await main(); diff --git a/pkg/workflow/js/add_reaction_and_edit_comment.test.cjs b/pkg/workflow/js/add_reaction_and_edit_comment.test.cjs index 97c3a2b0c1c..eab57a65d7a 100644 --- a/pkg/workflow/js/add_reaction_and_edit_comment.test.cjs +++ b/pkg/workflow/js/add_reaction_and_edit_comment.test.cjs @@ -86,8 +86,6 @@ describe("add_reaction_and_edit_comment.cjs", () => { // Reset environment variables delete process.env.GITHUB_AW_REACTION; - delete process.env.GITHUB_AW_COMMAND; - delete process.env.GITHUB_AW_WORKFLOW_NAME; // Reset context to default state global.context.eventName = "issues"; @@ -139,7 +137,7 @@ describe("add_reaction_and_edit_comment.cjs", () => { }); describe("Pull request reactions", () => { - it("should add reaction to pull request successfully (no comment)", async () => { + it("should add reaction to pull request successfully", async () => { process.env.GITHUB_AW_REACTION = "heart"; // NO GITHUB_AW_COMMAND set - this is NOT a command workflow global.context.eventName = "pull_request"; @@ -163,11 +161,7 @@ describe("add_reaction_and_edit_comment.cjs", () => { }) ); - // Verify only 1 call was made (reaction, no comment) - expect(mockGithub.request).toHaveBeenCalledTimes(1); - expect(mockCore.setOutput).toHaveBeenCalledWith("reaction-id", "789"); - expect(mockCore.setOutput).not.toHaveBeenCalledWith("comment-id", expect.anything()); }); }); @@ -335,231 +329,6 @@ describe("add_reaction_and_edit_comment.cjs", () => { }); }); - describe("Comment creation (always creates new comments)", () => { - it("should NOT create comment for issue event (non-command workflow)", async () => { - process.env.GITHUB_AW_REACTION = "eyes"; - process.env.GITHUB_AW_WORKFLOW_NAME = "Test Workflow"; - // NO GITHUB_AW_COMMAND set - this is NOT a command workflow - global.context.eventName = "issues"; - global.context.payload = { - issue: { number: 123 }, - repository: { html_url: "https://github.com/testowner/testrepo" }, - }; - - // Mock reaction call only (no comment creation) - mockGithub.request.mockResolvedValueOnce({ - data: { id: 456 }, - }); - - // Execute the script - await eval(`(async () => { ${reactionScript} })()`); - - // Verify reaction was added - expect(mockGithub.request).toHaveBeenCalledWith( - "POST /repos/testowner/testrepo/issues/123/reactions", - expect.objectContaining({ - content: "eyes", - }) - ); - - // Verify comment was NOT created (only 1 call for reaction) - expect(mockGithub.request).toHaveBeenCalledTimes(1); - - // Verify only reaction output was set, not comment outputs - expect(mockCore.setOutput).toHaveBeenCalledWith("reaction-id", "456"); - expect(mockCore.setOutput).not.toHaveBeenCalledWith("comment-id", expect.anything()); - }); - - it("should create new comment for issue_comment event (not edit)", async () => { - process.env.GITHUB_AW_REACTION = "eyes"; - process.env.GITHUB_AW_WORKFLOW_NAME = "Test Workflow"; - process.env.GITHUB_AW_COMMAND = "test-bot"; // Command workflow - global.context.eventName = "issue_comment"; - global.context.payload = { - issue: { number: 123 }, - comment: { id: 456 }, - repository: { html_url: "https://github.com/testowner/testrepo" }, - }; - - // Mock reaction call - mockGithub.request - .mockResolvedValueOnce({ - data: { id: 111 }, - }) - // Mock comment creation (not GET for edit) - .mockResolvedValueOnce({ - data: { id: 789, html_url: "https://github.com/testowner/testrepo/issues/123#issuecomment-789" }, - }); - - // Execute the script - await eval(`(async () => { ${reactionScript} })()`); - - // Verify new comment was created, NOT edited - // Should be POST to comments endpoint, not GET then PATCH to specific comment - expect(mockGithub.request).toHaveBeenCalledWith( - "POST /repos/testowner/testrepo/issues/comments/456", - expect.objectContaining({ - body: expect.stringContaining("Agentic [Test Workflow]"), - }) - ); - - // Verify GET (for editing) was NOT called - expect(mockGithub.request).not.toHaveBeenCalledWith("GET /repos/testowner/testrepo/issues/comments/456", expect.anything()); - - // Verify outputs - expect(mockCore.setOutput).toHaveBeenCalledWith("comment-id", "789"); - expect(mockCore.setOutput).toHaveBeenCalledWith("comment-url", "https://github.com/testowner/testrepo/issues/123#issuecomment-789"); - expect(mockCore.setOutput).toHaveBeenCalledWith("comment-repo", "testowner/testrepo"); - }); - - it("should create new comment for pull_request_review_comment event (not edit)", async () => { - process.env.GITHUB_AW_REACTION = "rocket"; - process.env.GITHUB_AW_WORKFLOW_NAME = "PR Review Bot"; - process.env.GITHUB_AW_COMMAND = "review-bot"; // Command workflow - global.context.eventName = "pull_request_review_comment"; - global.context.payload = { - pull_request: { number: 456 }, - comment: { id: 789 }, - repository: { html_url: "https://github.com/testowner/testrepo" }, - }; - - // Mock reaction call - mockGithub.request - .mockResolvedValueOnce({ - data: { id: 222 }, - }) - // Mock comment creation - .mockResolvedValueOnce({ - data: { id: 999, html_url: "https://github.com/testowner/testrepo/pull/456#discussion_r999" }, - }); - - // Execute the script - await eval(`(async () => { ${reactionScript} })()`); - - // Verify new comment was created - expect(mockGithub.request).toHaveBeenCalledWith( - "POST /repos/testowner/testrepo/pulls/comments/789", - expect.objectContaining({ - body: expect.stringContaining("Agentic [PR Review Bot]"), - }) - ); - - // Verify GET (for editing) was NOT called - expect(mockGithub.request).not.toHaveBeenCalledWith("GET /repos/testowner/testrepo/pulls/comments/789", expect.anything()); - - // Verify outputs - expect(mockCore.setOutput).toHaveBeenCalledWith("comment-id", "999"); - expect(mockCore.setOutput).toHaveBeenCalledWith("comment-url", "https://github.com/testowner/testrepo/pull/456#discussion_r999"); - expect(mockCore.setOutput).toHaveBeenCalledWith("comment-repo", "testowner/testrepo"); - }); - - it("should NOT create comment on discussion (non-command workflow)", async () => { - process.env.GITHUB_AW_REACTION = "eyes"; - process.env.GITHUB_AW_WORKFLOW_NAME = "Test Workflow"; - // NO GITHUB_AW_COMMAND set - this is NOT a command workflow - global.context.eventName = "discussion"; - global.context.payload = { - discussion: { number: 10 }, - repository: { html_url: "https://github.com/testowner/testrepo" }, - }; - - // Mock GraphQL query to get discussion ID - mockGithub.graphql - .mockResolvedValueOnce({ - repository: { - discussion: { - id: "D_kwDOABcD1M4AaBbC", - url: "https://github.com/testowner/testrepo/discussions/10", - }, - }, - }) - // Mock GraphQL mutation to add reaction - .mockResolvedValueOnce({ - addReaction: { - reaction: { - id: "MDg6UmVhY3Rpb24xMjM0NTY3ODk=", - content: "EYES", - }, - }, - }); - - // Execute the script - await eval(`(async () => { ${reactionScript} })()`); - - // Verify reaction was added (2 GraphQL calls: get discussion ID + add reaction) - expect(mockGithub.graphql).toHaveBeenCalledTimes(2); - - // Verify comment was NOT created (no addDiscussionComment mutation) - expect(mockGithub.graphql).not.toHaveBeenCalledWith(expect.stringContaining("addDiscussionComment"), expect.anything()); - - // Verify only reaction output was set - expect(mockCore.setOutput).toHaveBeenCalledWith("reaction-id", "MDg6UmVhY3Rpb24xMjM0NTY3ODk="); - expect(mockCore.setOutput).not.toHaveBeenCalledWith("comment-id", expect.anything()); - }); - - it("should create new comment for discussion_comment events", async () => { - process.env.GITHUB_AW_REACTION = "eyes"; - process.env.GITHUB_AW_COMMAND = "test-bot"; // Command workflow - process.env.GITHUB_AW_WORKFLOW_NAME = "Discussion Bot"; - global.context.eventName = "discussion_comment"; - global.context.payload = { - discussion: { number: 10 }, - comment: { - id: 123, - node_id: "DC_kwDOABcD1M4AaBbC", - }, - repository: { html_url: "https://github.com/testowner/testrepo" }, - }; - - // Mock GraphQL mutation to add reaction - mockGithub.graphql - .mockResolvedValueOnce({ - addReaction: { - reaction: { - id: "MDg6UmVhY3Rpb24xMjM0NTY3ODk=", - content: "EYES", - }, - }, - }) - // Mock GraphQL query to get discussion ID for comment creation - .mockResolvedValueOnce({ - repository: { - discussion: { - id: "D_kwDOABcD1M4AaBbC", - }, - }, - }) - // Mock GraphQL mutation to add comment - .mockResolvedValueOnce({ - addDiscussionComment: { - comment: { - id: "DC_kwDOABcD1M4AaBbE", - url: "https://github.com/testowner/testrepo/discussions/10#discussioncomment-789", - }, - }, - }); - - // Execute the script - await eval(`(async () => { ${reactionScript} })()`); - - // Verify comment was created - expect(mockGithub.graphql).toHaveBeenCalledWith( - expect.stringContaining("addDiscussionComment"), - expect.objectContaining({ - dId: "D_kwDOABcD1M4AaBbC", - body: expect.stringContaining("Agentic [Discussion Bot]"), - }) - ); - - expect(mockCore.setOutput).toHaveBeenCalledWith("comment-id", "DC_kwDOABcD1M4AaBbE"); - expect(mockCore.setOutput).toHaveBeenCalledWith( - "comment-url", - "https://github.com/testowner/testrepo/discussions/10#discussioncomment-789" - ); - expect(mockCore.setOutput).toHaveBeenCalledWith("comment-repo", "testowner/testrepo"); - }); - }); - describe("Error handling", () => { it("should handle missing discussion number", async () => { process.env.GITHUB_AW_REACTION = "eyes"; From 4007d35a8b5cc5d6f798877619bbf1f2cf6fb189 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Oct 2025 04:42:32 +0000 Subject: [PATCH 4/5] Revert last commit and rename to clarify comment creation only Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .github/workflows/brave.lock.yml | 3 + .../workflows/changeset-generator.lock.yml | 3 + .github/workflows/dev.lock.yml | 3 + .github/workflows/issue-classifier.lock.yml | 3 + .github/workflows/pdf-summary.lock.yml | 3 + .github/workflows/plan.lock.yml | 3 + .github/workflows/poem-bot.lock.yml | 3 + .github/workflows/q.lock.yml | 3 + .github/workflows/scout.lock.yml | 3 + .github/workflows/tidy.lock.yml | 3 + .github/workflows/unbloat-docs.lock.yml | 3 + .../js/add_reaction_and_edit_comment.cjs | 214 +++++++++++++++- .../js/add_reaction_and_edit_comment.test.cjs | 233 +++++++++++++++++- 13 files changed, 476 insertions(+), 4 deletions(-) diff --git a/.github/workflows/brave.lock.yml b/.github/workflows/brave.lock.yml index 07cf491a22e..fe7ad65d4e9 100644 --- a/.github/workflows/brave.lock.yml +++ b/.github/workflows/brave.lock.yml @@ -370,6 +370,7 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/comments`; + shouldEditComment = true; break; case "issue_comment": const commentId = context.payload?.comment?.id; @@ -389,6 +390,7 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/comments`; + shouldEditComment = true; break; case "pull_request_review_comment": const reviewCommentId = context.payload?.comment?.id; @@ -409,6 +411,7 @@ jobs: const discussion = await getDiscussionId(owner, repo, discussionNumber); reactionEndpoint = discussion.id; commentUpdateEndpoint = `discussion:${discussionNumber}`; + shouldEditComment = true; break; case "discussion_comment": const discussionCommentNumber = context.payload?.discussion?.number; diff --git a/.github/workflows/changeset-generator.lock.yml b/.github/workflows/changeset-generator.lock.yml index 1fc42b874df..973e233aaaf 100644 --- a/.github/workflows/changeset-generator.lock.yml +++ b/.github/workflows/changeset-generator.lock.yml @@ -362,6 +362,7 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/comments`; + shouldEditComment = true; break; case "issue_comment": const commentId = context.payload?.comment?.id; @@ -381,6 +382,7 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/comments`; + shouldEditComment = true; break; case "pull_request_review_comment": const reviewCommentId = context.payload?.comment?.id; @@ -401,6 +403,7 @@ jobs: const discussion = await getDiscussionId(owner, repo, discussionNumber); reactionEndpoint = discussion.id; commentUpdateEndpoint = `discussion:${discussionNumber}`; + shouldEditComment = true; break; case "discussion_comment": const discussionCommentNumber = context.payload?.discussion?.number; diff --git a/.github/workflows/dev.lock.yml b/.github/workflows/dev.lock.yml index 9da03219885..ec00dee3eff 100644 --- a/.github/workflows/dev.lock.yml +++ b/.github/workflows/dev.lock.yml @@ -282,6 +282,7 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/comments`; + shouldEditComment = true; break; case "issue_comment": const commentId = context.payload?.comment?.id; @@ -301,6 +302,7 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/comments`; + shouldEditComment = true; break; case "pull_request_review_comment": const reviewCommentId = context.payload?.comment?.id; @@ -321,6 +323,7 @@ jobs: const discussion = await getDiscussionId(owner, repo, discussionNumber); reactionEndpoint = discussion.id; commentUpdateEndpoint = `discussion:${discussionNumber}`; + shouldEditComment = true; break; case "discussion_comment": const discussionCommentNumber = context.payload?.discussion?.number; diff --git a/.github/workflows/issue-classifier.lock.yml b/.github/workflows/issue-classifier.lock.yml index 12fcab24804..aecbb1d663f 100644 --- a/.github/workflows/issue-classifier.lock.yml +++ b/.github/workflows/issue-classifier.lock.yml @@ -359,6 +359,7 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/comments`; + shouldEditComment = true; break; case "issue_comment": const commentId = context.payload?.comment?.id; @@ -378,6 +379,7 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/comments`; + shouldEditComment = true; break; case "pull_request_review_comment": const reviewCommentId = context.payload?.comment?.id; @@ -398,6 +400,7 @@ jobs: const discussion = await getDiscussionId(owner, repo, discussionNumber); reactionEndpoint = discussion.id; commentUpdateEndpoint = `discussion:${discussionNumber}`; + shouldEditComment = true; break; case "discussion_comment": const discussionCommentNumber = context.payload?.discussion?.number; diff --git a/.github/workflows/pdf-summary.lock.yml b/.github/workflows/pdf-summary.lock.yml index fd62cd0b2aa..5e51b548e1f 100644 --- a/.github/workflows/pdf-summary.lock.yml +++ b/.github/workflows/pdf-summary.lock.yml @@ -391,6 +391,7 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/comments`; + shouldEditComment = true; break; case "issue_comment": const commentId = context.payload?.comment?.id; @@ -410,6 +411,7 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/comments`; + shouldEditComment = true; break; case "pull_request_review_comment": const reviewCommentId = context.payload?.comment?.id; @@ -430,6 +432,7 @@ jobs: const discussion = await getDiscussionId(owner, repo, discussionNumber); reactionEndpoint = discussion.id; commentUpdateEndpoint = `discussion:${discussionNumber}`; + shouldEditComment = true; break; case "discussion_comment": const discussionCommentNumber = context.payload?.discussion?.number; diff --git a/.github/workflows/plan.lock.yml b/.github/workflows/plan.lock.yml index e99ac36d730..91b66b56ff3 100644 --- a/.github/workflows/plan.lock.yml +++ b/.github/workflows/plan.lock.yml @@ -361,6 +361,7 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/comments`; + shouldEditComment = true; break; case "issue_comment": const commentId = context.payload?.comment?.id; @@ -380,6 +381,7 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/comments`; + shouldEditComment = true; break; case "pull_request_review_comment": const reviewCommentId = context.payload?.comment?.id; @@ -400,6 +402,7 @@ jobs: const discussion = await getDiscussionId(owner, repo, discussionNumber); reactionEndpoint = discussion.id; commentUpdateEndpoint = `discussion:${discussionNumber}`; + shouldEditComment = true; break; case "discussion_comment": const discussionCommentNumber = context.payload?.discussion?.number; diff --git a/.github/workflows/poem-bot.lock.yml b/.github/workflows/poem-bot.lock.yml index a6d6b9f85a7..cfba46ec886 100644 --- a/.github/workflows/poem-bot.lock.yml +++ b/.github/workflows/poem-bot.lock.yml @@ -402,6 +402,7 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/comments`; + shouldEditComment = true; break; case "issue_comment": const commentId = context.payload?.comment?.id; @@ -421,6 +422,7 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/comments`; + shouldEditComment = true; break; case "pull_request_review_comment": const reviewCommentId = context.payload?.comment?.id; @@ -441,6 +443,7 @@ jobs: const discussion = await getDiscussionId(owner, repo, discussionNumber); reactionEndpoint = discussion.id; commentUpdateEndpoint = `discussion:${discussionNumber}`; + shouldEditComment = true; break; case "discussion_comment": const discussionCommentNumber = context.payload?.discussion?.number; diff --git a/.github/workflows/q.lock.yml b/.github/workflows/q.lock.yml index 41f424c3e0a..f80c3c03cac 100644 --- a/.github/workflows/q.lock.yml +++ b/.github/workflows/q.lock.yml @@ -413,6 +413,7 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/comments`; + shouldEditComment = true; break; case "issue_comment": const commentId = context.payload?.comment?.id; @@ -432,6 +433,7 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/comments`; + shouldEditComment = true; break; case "pull_request_review_comment": const reviewCommentId = context.payload?.comment?.id; @@ -452,6 +454,7 @@ jobs: const discussion = await getDiscussionId(owner, repo, discussionNumber); reactionEndpoint = discussion.id; commentUpdateEndpoint = `discussion:${discussionNumber}`; + shouldEditComment = true; break; case "discussion_comment": const discussionCommentNumber = context.payload?.discussion?.number; diff --git a/.github/workflows/scout.lock.yml b/.github/workflows/scout.lock.yml index 5c69003ec2b..dd7803feb7b 100644 --- a/.github/workflows/scout.lock.yml +++ b/.github/workflows/scout.lock.yml @@ -425,6 +425,7 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/comments`; + shouldEditComment = true; break; case "issue_comment": const commentId = context.payload?.comment?.id; @@ -444,6 +445,7 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/comments`; + shouldEditComment = true; break; case "pull_request_review_comment": const reviewCommentId = context.payload?.comment?.id; @@ -464,6 +466,7 @@ jobs: const discussion = await getDiscussionId(owner, repo, discussionNumber); reactionEndpoint = discussion.id; commentUpdateEndpoint = `discussion:${discussionNumber}`; + shouldEditComment = true; break; case "discussion_comment": const discussionCommentNumber = context.payload?.discussion?.number; diff --git a/.github/workflows/tidy.lock.yml b/.github/workflows/tidy.lock.yml index 80b7f27b0cc..84fb4aff849 100644 --- a/.github/workflows/tidy.lock.yml +++ b/.github/workflows/tidy.lock.yml @@ -212,6 +212,7 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/comments`; + shouldEditComment = true; break; case "issue_comment": const commentId = context.payload?.comment?.id; @@ -231,6 +232,7 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/comments`; + shouldEditComment = true; break; case "pull_request_review_comment": const reviewCommentId = context.payload?.comment?.id; @@ -251,6 +253,7 @@ jobs: const discussion = await getDiscussionId(owner, repo, discussionNumber); reactionEndpoint = discussion.id; commentUpdateEndpoint = `discussion:${discussionNumber}`; + shouldEditComment = true; break; case "discussion_comment": const discussionCommentNumber = context.payload?.discussion?.number; diff --git a/.github/workflows/unbloat-docs.lock.yml b/.github/workflows/unbloat-docs.lock.yml index f0fd53059d5..5d9430ff3ce 100644 --- a/.github/workflows/unbloat-docs.lock.yml +++ b/.github/workflows/unbloat-docs.lock.yml @@ -216,6 +216,7 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/comments`; + shouldEditComment = true; break; case "issue_comment": const commentId = context.payload?.comment?.id; @@ -235,6 +236,7 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/comments`; + shouldEditComment = true; break; case "pull_request_review_comment": const reviewCommentId = context.payload?.comment?.id; @@ -255,6 +257,7 @@ jobs: const discussion = await getDiscussionId(owner, repo, discussionNumber); reactionEndpoint = discussion.id; commentUpdateEndpoint = `discussion:${discussionNumber}`; + shouldEditComment = true; break; case "discussion_comment": const discussionCommentNumber = context.payload?.discussion?.number; diff --git a/pkg/workflow/js/add_reaction_and_edit_comment.cjs b/pkg/workflow/js/add_reaction_and_edit_comment.cjs index 7b15ea14012..ab7a82c9994 100644 --- a/pkg/workflow/js/add_reaction_and_edit_comment.cjs +++ b/pkg/workflow/js/add_reaction_and_edit_comment.cjs @@ -1,8 +1,17 @@ async function main() { // Read inputs from environment variables const reaction = process.env.GITHUB_AW_REACTION || "eyes"; + const command = process.env.GITHUB_AW_COMMAND; // Only present for command workflows + const runId = context.runId; + const githubServer = process.env.GITHUB_SERVER_URL || "https://github.com"; + const runUrl = context.payload.repository + ? `${context.payload.repository.html_url}/actions/runs/${runId}` + : `${githubServer}/${context.repo.owner}/${context.repo.repo}/actions/runs/${runId}`; core.info(`Reaction type: ${reaction}`); + core.info(`Command name: ${command || "none"}`); + core.info(`Run ID: ${runId}`); + core.info(`Run URL: ${runUrl}`); // Validate reaction type const validReactions = ["+1", "-1", "laugh", "confused", "heart", "hooray", "rocket", "eyes"]; @@ -13,6 +22,8 @@ async function main() { // Determine the API endpoint based on the event type let reactionEndpoint; + let commentUpdateEndpoint; + let shouldCreateComment = false; const eventName = context.eventName; const owner = context.repo.owner; const repo = context.repo.repo; @@ -26,6 +37,7 @@ async function main() { return; } reactionEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/reactions`; + commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/comments`; break; case "issue_comment": @@ -35,6 +47,9 @@ async function main() { return; } reactionEndpoint = `/repos/${owner}/${repo}/issues/comments/${commentId}/reactions`; + commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/comments/${commentId}`; + // Only create comments for command workflows + shouldCreateComment = command ? true : false; break; case "pull_request": @@ -45,6 +60,7 @@ async function main() { } // PRs are "issues" for the reactions endpoint reactionEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/reactions`; + commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/comments`; break; case "pull_request_review_comment": @@ -54,6 +70,9 @@ async function main() { return; } reactionEndpoint = `/repos/${owner}/${repo}/pulls/comments/${reviewCommentId}/reactions`; + commentUpdateEndpoint = `/repos/${owner}/${repo}/pulls/comments/${reviewCommentId}`; + // Only create comments for command workflows + shouldCreateComment = command ? true : false; break; case "discussion": @@ -65,6 +84,7 @@ async function main() { // Discussions use GraphQL API - get the node ID const discussion = await getDiscussionId(owner, repo, discussionNumber); reactionEndpoint = discussion.id; // Store node ID for GraphQL + commentUpdateEndpoint = `discussion:${discussionNumber}`; // Special format to indicate discussion break; case "discussion_comment": @@ -81,6 +101,9 @@ async function main() { return; } reactionEndpoint = commentNodeId; // Store node ID for GraphQL + commentUpdateEndpoint = `discussion_comment:${discussionCommentNumber}:${discussionCommentId}`; // Special format + // Only create comments for command workflows + shouldCreateComment = command ? true : false; break; default: @@ -90,7 +113,7 @@ async function main() { core.info(`Reaction API endpoint: ${reactionEndpoint}`); - // Add reaction + // Add reaction first // For discussions, reactionEndpoint is a node ID (GraphQL), otherwise it's a REST API path const isDiscussionEvent = eventName === "discussion" || eventName === "discussion_comment"; if (isDiscussionEvent) { @@ -98,10 +121,22 @@ async function main() { } else { await addReaction(reactionEndpoint, reaction); } + + // Then add comment if applicable + if (shouldCreateComment && commentUpdateEndpoint) { + core.info(`Comment endpoint: ${commentUpdateEndpoint}`); + await addCommentWithWorkflowLink(commentUpdateEndpoint, runUrl, eventName); + } else { + if (!command && commentUpdateEndpoint) { + core.info("Skipping comment creation - only available for command workflows"); + } else { + core.info(`Skipping comment for event type: ${eventName}`); + } + } } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); - core.error(`Failed to process reaction: ${errorMessage}`); - core.setFailed(`Failed to process reaction: ${errorMessage}`); + core.error(`Failed to process reaction and comment creation: ${errorMessage}`); + core.setFailed(`Failed to process reaction and comment creation: ${errorMessage}`); } } @@ -200,4 +235,177 @@ async function getDiscussionId(owner, repo, discussionNumber) { }; } +/** + * Get the node ID for a discussion comment + * @param {string} owner - Repository owner + * @param {string} repo - Repository name + * @param {number} discussionNumber - Discussion number + * @param {number} commentId - Comment ID (database ID, not node ID) + * @returns {Promise<{id: string, url: string}>} Comment details + */ +async function getDiscussionCommentId(owner, repo, discussionNumber, commentId) { + // First, get the discussion ID + const discussion = await getDiscussionId(owner, repo, discussionNumber); + if (!discussion) throw new Error(`Discussion #${discussionNumber} not found in ${owner}/${repo}`); + + // Then fetch the comment by traversing discussion comments + // Note: GitHub's GraphQL API doesn't provide a direct way to query comment by database ID + // We need to use the comment's node ID from the event payload if available + // For now, we'll use a simplified approach - the commentId from context.payload.comment.node_id + + // If the event payload provides node_id, we can use it directly + // Otherwise, this would need to fetch all comments and find the matching one + const nodeId = context.payload?.comment?.node_id; + if (nodeId) { + return { + id: nodeId, + url: context.payload.comment?.html_url || discussion?.url, + }; + } + + throw new Error(`Discussion comment node ID not found in event payload for comment ${commentId}`); +} + +/** + * Add a comment with a workflow run link + * @param {string} endpoint - The GitHub API endpoint to create the comment (or special format for discussions) + * @param {string} runUrl - The URL of the workflow run + * @param {string} eventName - The event type (to determine the comment text) + */ +async function addCommentWithWorkflowLink(endpoint, runUrl, eventName) { + try { + // Get workflow name from environment variable + const workflowName = process.env.GITHUB_AW_WORKFLOW_NAME || "Workflow"; + + // Handle discussion events specially + if (eventName === "discussion") { + // Parse discussion number from special format: "discussion:NUMBER" + const discussionNumber = parseInt(endpoint.split(":")[1], 10); + const workflowLinkText = `Agentic [${workflowName}](${runUrl}) triggered by this discussion.`; + + // Create a new comment on the discussion using GraphQL + const { repository } = await github.graphql( + ` + query($owner: String!, $repo: String!, $num: Int!) { + repository(owner: $owner, name: $repo) { + discussion(number: $num) { + id + } + } + }`, + { owner: context.repo.owner, repo: context.repo.repo, num: discussionNumber } + ); + + const discussionId = repository.discussion.id; + + const result = await github.graphql( + ` + mutation($dId: ID!, $body: String!) { + addDiscussionComment(input: { discussionId: $dId, body: $body }) { + comment { + id + url + } + } + }`, + { dId: discussionId, body: workflowLinkText } + ); + + const comment = result.addDiscussionComment.comment; + core.info(`Successfully created discussion comment with workflow link`); + core.info(`Comment ID: ${comment.id}`); + core.info(`Comment URL: ${comment.url}`); + core.info(`Comment Repo: ${context.repo.owner}/${context.repo.repo}`); + core.setOutput("comment-id", comment.id); + core.setOutput("comment-url", comment.url); + core.setOutput("comment-repo", `${context.repo.owner}/${context.repo.repo}`); + return; + } else if (eventName === "discussion_comment") { + // Parse discussion number from special format: "discussion_comment:NUMBER:COMMENT_ID" + const discussionNumber = parseInt(endpoint.split(":")[1], 10); + const workflowLinkText = `Agentic [${workflowName}](${runUrl}) triggered by this discussion comment.`; + + // Create a new comment on the discussion using GraphQL + const { repository } = await github.graphql( + ` + query($owner: String!, $repo: String!, $num: Int!) { + repository(owner: $owner, name: $repo) { + discussion(number: $num) { + id + } + } + }`, + { owner: context.repo.owner, repo: context.repo.repo, num: discussionNumber } + ); + + const discussionId = repository.discussion.id; + + const result = await github.graphql( + ` + mutation($dId: ID!, $body: String!) { + addDiscussionComment(input: { discussionId: $dId, body: $body }) { + comment { + id + url + } + } + }`, + { dId: discussionId, body: workflowLinkText } + ); + + const comment = result.addDiscussionComment.comment; + core.info(`Successfully created discussion comment with workflow link`); + core.info(`Comment ID: ${comment.id}`); + core.info(`Comment URL: ${comment.url}`); + core.info(`Comment Repo: ${context.repo.owner}/${context.repo.repo}`); + core.setOutput("comment-id", comment.id); + core.setOutput("comment-url", comment.url); + core.setOutput("comment-repo", `${context.repo.owner}/${context.repo.repo}`); + return; + } + + // Always create a new comment (never edit existing comments) + let eventTypeDescription; + switch (eventName) { + case "issues": + eventTypeDescription = "issue"; + break; + case "pull_request": + eventTypeDescription = "pull request"; + break; + case "issue_comment": + eventTypeDescription = "issue comment"; + break; + case "pull_request_review_comment": + eventTypeDescription = "pull request review comment"; + break; + default: + eventTypeDescription = "event"; + } + + const workflowLinkText = `Agentic [${workflowName}](${runUrl}) triggered by this ${eventTypeDescription}.`; + + const createResponse = await github.request("POST " + endpoint, { + body: workflowLinkText, + headers: { + Accept: "application/vnd.github+json", + }, + }); + + core.info(`Successfully created comment with workflow link`); + core.info(`Comment ID: ${createResponse.data.id}`); + core.info(`Comment URL: ${createResponse.data.html_url}`); + core.info(`Comment Repo: ${context.repo.owner}/${context.repo.repo}`); + core.setOutput("comment-id", createResponse.data.id.toString()); + core.setOutput("comment-url", createResponse.data.html_url); + core.setOutput("comment-repo", `${context.repo.owner}/${context.repo.repo}`); + } catch (error) { + // Don't fail the entire job if comment creation fails - just log it + const errorMessage = error instanceof Error ? error.message : String(error); + core.warning( + "Failed to create comment with workflow link (This is not critical - the reaction was still added successfully): " + errorMessage + ); + } +} + await main(); diff --git a/pkg/workflow/js/add_reaction_and_edit_comment.test.cjs b/pkg/workflow/js/add_reaction_and_edit_comment.test.cjs index eab57a65d7a..97c3a2b0c1c 100644 --- a/pkg/workflow/js/add_reaction_and_edit_comment.test.cjs +++ b/pkg/workflow/js/add_reaction_and_edit_comment.test.cjs @@ -86,6 +86,8 @@ describe("add_reaction_and_edit_comment.cjs", () => { // Reset environment variables delete process.env.GITHUB_AW_REACTION; + delete process.env.GITHUB_AW_COMMAND; + delete process.env.GITHUB_AW_WORKFLOW_NAME; // Reset context to default state global.context.eventName = "issues"; @@ -137,7 +139,7 @@ describe("add_reaction_and_edit_comment.cjs", () => { }); describe("Pull request reactions", () => { - it("should add reaction to pull request successfully", async () => { + it("should add reaction to pull request successfully (no comment)", async () => { process.env.GITHUB_AW_REACTION = "heart"; // NO GITHUB_AW_COMMAND set - this is NOT a command workflow global.context.eventName = "pull_request"; @@ -161,7 +163,11 @@ describe("add_reaction_and_edit_comment.cjs", () => { }) ); + // Verify only 1 call was made (reaction, no comment) + expect(mockGithub.request).toHaveBeenCalledTimes(1); + expect(mockCore.setOutput).toHaveBeenCalledWith("reaction-id", "789"); + expect(mockCore.setOutput).not.toHaveBeenCalledWith("comment-id", expect.anything()); }); }); @@ -329,6 +335,231 @@ describe("add_reaction_and_edit_comment.cjs", () => { }); }); + describe("Comment creation (always creates new comments)", () => { + it("should NOT create comment for issue event (non-command workflow)", async () => { + process.env.GITHUB_AW_REACTION = "eyes"; + process.env.GITHUB_AW_WORKFLOW_NAME = "Test Workflow"; + // NO GITHUB_AW_COMMAND set - this is NOT a command workflow + global.context.eventName = "issues"; + global.context.payload = { + issue: { number: 123 }, + repository: { html_url: "https://github.com/testowner/testrepo" }, + }; + + // Mock reaction call only (no comment creation) + mockGithub.request.mockResolvedValueOnce({ + data: { id: 456 }, + }); + + // Execute the script + await eval(`(async () => { ${reactionScript} })()`); + + // Verify reaction was added + expect(mockGithub.request).toHaveBeenCalledWith( + "POST /repos/testowner/testrepo/issues/123/reactions", + expect.objectContaining({ + content: "eyes", + }) + ); + + // Verify comment was NOT created (only 1 call for reaction) + expect(mockGithub.request).toHaveBeenCalledTimes(1); + + // Verify only reaction output was set, not comment outputs + expect(mockCore.setOutput).toHaveBeenCalledWith("reaction-id", "456"); + expect(mockCore.setOutput).not.toHaveBeenCalledWith("comment-id", expect.anything()); + }); + + it("should create new comment for issue_comment event (not edit)", async () => { + process.env.GITHUB_AW_REACTION = "eyes"; + process.env.GITHUB_AW_WORKFLOW_NAME = "Test Workflow"; + process.env.GITHUB_AW_COMMAND = "test-bot"; // Command workflow + global.context.eventName = "issue_comment"; + global.context.payload = { + issue: { number: 123 }, + comment: { id: 456 }, + repository: { html_url: "https://github.com/testowner/testrepo" }, + }; + + // Mock reaction call + mockGithub.request + .mockResolvedValueOnce({ + data: { id: 111 }, + }) + // Mock comment creation (not GET for edit) + .mockResolvedValueOnce({ + data: { id: 789, html_url: "https://github.com/testowner/testrepo/issues/123#issuecomment-789" }, + }); + + // Execute the script + await eval(`(async () => { ${reactionScript} })()`); + + // Verify new comment was created, NOT edited + // Should be POST to comments endpoint, not GET then PATCH to specific comment + expect(mockGithub.request).toHaveBeenCalledWith( + "POST /repos/testowner/testrepo/issues/comments/456", + expect.objectContaining({ + body: expect.stringContaining("Agentic [Test Workflow]"), + }) + ); + + // Verify GET (for editing) was NOT called + expect(mockGithub.request).not.toHaveBeenCalledWith("GET /repos/testowner/testrepo/issues/comments/456", expect.anything()); + + // Verify outputs + expect(mockCore.setOutput).toHaveBeenCalledWith("comment-id", "789"); + expect(mockCore.setOutput).toHaveBeenCalledWith("comment-url", "https://github.com/testowner/testrepo/issues/123#issuecomment-789"); + expect(mockCore.setOutput).toHaveBeenCalledWith("comment-repo", "testowner/testrepo"); + }); + + it("should create new comment for pull_request_review_comment event (not edit)", async () => { + process.env.GITHUB_AW_REACTION = "rocket"; + process.env.GITHUB_AW_WORKFLOW_NAME = "PR Review Bot"; + process.env.GITHUB_AW_COMMAND = "review-bot"; // Command workflow + global.context.eventName = "pull_request_review_comment"; + global.context.payload = { + pull_request: { number: 456 }, + comment: { id: 789 }, + repository: { html_url: "https://github.com/testowner/testrepo" }, + }; + + // Mock reaction call + mockGithub.request + .mockResolvedValueOnce({ + data: { id: 222 }, + }) + // Mock comment creation + .mockResolvedValueOnce({ + data: { id: 999, html_url: "https://github.com/testowner/testrepo/pull/456#discussion_r999" }, + }); + + // Execute the script + await eval(`(async () => { ${reactionScript} })()`); + + // Verify new comment was created + expect(mockGithub.request).toHaveBeenCalledWith( + "POST /repos/testowner/testrepo/pulls/comments/789", + expect.objectContaining({ + body: expect.stringContaining("Agentic [PR Review Bot]"), + }) + ); + + // Verify GET (for editing) was NOT called + expect(mockGithub.request).not.toHaveBeenCalledWith("GET /repos/testowner/testrepo/pulls/comments/789", expect.anything()); + + // Verify outputs + expect(mockCore.setOutput).toHaveBeenCalledWith("comment-id", "999"); + expect(mockCore.setOutput).toHaveBeenCalledWith("comment-url", "https://github.com/testowner/testrepo/pull/456#discussion_r999"); + expect(mockCore.setOutput).toHaveBeenCalledWith("comment-repo", "testowner/testrepo"); + }); + + it("should NOT create comment on discussion (non-command workflow)", async () => { + process.env.GITHUB_AW_REACTION = "eyes"; + process.env.GITHUB_AW_WORKFLOW_NAME = "Test Workflow"; + // NO GITHUB_AW_COMMAND set - this is NOT a command workflow + global.context.eventName = "discussion"; + global.context.payload = { + discussion: { number: 10 }, + repository: { html_url: "https://github.com/testowner/testrepo" }, + }; + + // Mock GraphQL query to get discussion ID + mockGithub.graphql + .mockResolvedValueOnce({ + repository: { + discussion: { + id: "D_kwDOABcD1M4AaBbC", + url: "https://github.com/testowner/testrepo/discussions/10", + }, + }, + }) + // Mock GraphQL mutation to add reaction + .mockResolvedValueOnce({ + addReaction: { + reaction: { + id: "MDg6UmVhY3Rpb24xMjM0NTY3ODk=", + content: "EYES", + }, + }, + }); + + // Execute the script + await eval(`(async () => { ${reactionScript} })()`); + + // Verify reaction was added (2 GraphQL calls: get discussion ID + add reaction) + expect(mockGithub.graphql).toHaveBeenCalledTimes(2); + + // Verify comment was NOT created (no addDiscussionComment mutation) + expect(mockGithub.graphql).not.toHaveBeenCalledWith(expect.stringContaining("addDiscussionComment"), expect.anything()); + + // Verify only reaction output was set + expect(mockCore.setOutput).toHaveBeenCalledWith("reaction-id", "MDg6UmVhY3Rpb24xMjM0NTY3ODk="); + expect(mockCore.setOutput).not.toHaveBeenCalledWith("comment-id", expect.anything()); + }); + + it("should create new comment for discussion_comment events", async () => { + process.env.GITHUB_AW_REACTION = "eyes"; + process.env.GITHUB_AW_COMMAND = "test-bot"; // Command workflow + process.env.GITHUB_AW_WORKFLOW_NAME = "Discussion Bot"; + global.context.eventName = "discussion_comment"; + global.context.payload = { + discussion: { number: 10 }, + comment: { + id: 123, + node_id: "DC_kwDOABcD1M4AaBbC", + }, + repository: { html_url: "https://github.com/testowner/testrepo" }, + }; + + // Mock GraphQL mutation to add reaction + mockGithub.graphql + .mockResolvedValueOnce({ + addReaction: { + reaction: { + id: "MDg6UmVhY3Rpb24xMjM0NTY3ODk=", + content: "EYES", + }, + }, + }) + // Mock GraphQL query to get discussion ID for comment creation + .mockResolvedValueOnce({ + repository: { + discussion: { + id: "D_kwDOABcD1M4AaBbC", + }, + }, + }) + // Mock GraphQL mutation to add comment + .mockResolvedValueOnce({ + addDiscussionComment: { + comment: { + id: "DC_kwDOABcD1M4AaBbE", + url: "https://github.com/testowner/testrepo/discussions/10#discussioncomment-789", + }, + }, + }); + + // Execute the script + await eval(`(async () => { ${reactionScript} })()`); + + // Verify comment was created + expect(mockGithub.graphql).toHaveBeenCalledWith( + expect.stringContaining("addDiscussionComment"), + expect.objectContaining({ + dId: "D_kwDOABcD1M4AaBbC", + body: expect.stringContaining("Agentic [Discussion Bot]"), + }) + ); + + expect(mockCore.setOutput).toHaveBeenCalledWith("comment-id", "DC_kwDOABcD1M4AaBbE"); + expect(mockCore.setOutput).toHaveBeenCalledWith( + "comment-url", + "https://github.com/testowner/testrepo/discussions/10#discussioncomment-789" + ); + expect(mockCore.setOutput).toHaveBeenCalledWith("comment-repo", "testowner/testrepo"); + }); + }); + describe("Error handling", () => { it("should handle missing discussion number", async () => { process.env.GITHUB_AW_REACTION = "eyes"; From d812710462b19ac648e299bf52c1d52e5de2bc0f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Oct 2025 04:59:00 +0000 Subject: [PATCH 5/5] Fix comment creation to post to parent thread, not comment itself Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .github/workflows/brave.lock.yml | 25 ++++++++----------- .../workflows/changeset-generator.lock.yml | 25 ++++++++----------- .github/workflows/dev.lock.yml | 25 ++++++++----------- .github/workflows/issue-classifier.lock.yml | 25 ++++++++----------- .github/workflows/pdf-summary.lock.yml | 25 ++++++++----------- .github/workflows/plan.lock.yml | 25 ++++++++----------- .github/workflows/poem-bot.lock.yml | 25 ++++++++----------- .github/workflows/q.lock.yml | 25 ++++++++----------- .github/workflows/scout.lock.yml | 25 ++++++++----------- .github/workflows/tidy.lock.yml | 25 ++++++++----------- .github/workflows/unbloat-docs.lock.yml | 25 ++++++++----------- .../js/add_reaction_and_edit_comment.cjs | 16 ++++++++++-- .../js/add_reaction_and_edit_comment.test.cjs | 19 +++++++------- 13 files changed, 145 insertions(+), 165 deletions(-) diff --git a/.github/workflows/brave.lock.yml b/.github/workflows/brave.lock.yml index fe7ad65d4e9..febfd0bfeb9 100644 --- a/.github/workflows/brave.lock.yml +++ b/.github/workflows/brave.lock.yml @@ -356,7 +356,7 @@ jobs: } let reactionEndpoint; let commentUpdateEndpoint; - let shouldEditComment = false; + let shouldCreateComment = false; const eventName = context.eventName; const owner = context.repo.owner; const repo = context.repo.repo; @@ -370,7 +370,6 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/comments`; - shouldEditComment = true; break; case "issue_comment": const commentId = context.payload?.comment?.id; @@ -380,7 +379,7 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/comments/${commentId}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/comments/${commentId}`; - shouldEditComment = command ? true : false; + shouldCreateComment = command ? true : false; break; case "pull_request": const prNumber = context.payload?.pull_request?.number; @@ -390,7 +389,6 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/comments`; - shouldEditComment = true; break; case "pull_request_review_comment": const reviewCommentId = context.payload?.comment?.id; @@ -400,7 +398,7 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/pulls/comments/${reviewCommentId}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/pulls/comments/${reviewCommentId}`; - shouldEditComment = command ? true : false; + shouldCreateComment = command ? true : false; break; case "discussion": const discussionNumber = context.payload?.discussion?.number; @@ -411,7 +409,6 @@ jobs: const discussion = await getDiscussionId(owner, repo, discussionNumber); reactionEndpoint = discussion.id; commentUpdateEndpoint = `discussion:${discussionNumber}`; - shouldEditComment = true; break; case "discussion_comment": const discussionCommentNumber = context.payload?.discussion?.number; @@ -427,7 +424,7 @@ jobs: } reactionEndpoint = commentNodeId; commentUpdateEndpoint = `discussion_comment:${discussionCommentNumber}:${discussionCommentId}`; - shouldEditComment = command ? true : false; + shouldCreateComment = command ? true : false; break; default: core.setFailed(`Unsupported event type: ${eventName}`); @@ -440,20 +437,20 @@ jobs: } else { await addReaction(reactionEndpoint, reaction); } - if (shouldEditComment && commentUpdateEndpoint) { + if (shouldCreateComment && commentUpdateEndpoint) { core.info(`Comment endpoint: ${commentUpdateEndpoint}`); - await addOrEditCommentWithWorkflowLink(commentUpdateEndpoint, runUrl, eventName); + await addCommentWithWorkflowLink(commentUpdateEndpoint, runUrl, eventName); } else { if (!command && commentUpdateEndpoint) { - core.info("Skipping comment edit - only available for command workflows"); + core.info("Skipping comment creation - only available for command workflows"); } else { core.info(`Skipping comment for event type: ${eventName}`); } } } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); - core.error(`Failed to process reaction and comment edit: ${errorMessage}`); - core.setFailed(`Failed to process reaction and comment edit: ${errorMessage}`); + core.error(`Failed to process reaction and comment creation: ${errorMessage}`); + core.setFailed(`Failed to process reaction and comment creation: ${errorMessage}`); } } async function addReaction(endpoint, reaction) { @@ -536,7 +533,7 @@ jobs: } throw new Error(`Discussion comment node ID not found in event payload for comment ${commentId}`); } - async function addOrEditCommentWithWorkflowLink(endpoint, runUrl, eventName) { + async function addCommentWithWorkflowLink(endpoint, runUrl, eventName) { try { const workflowName = process.env.GITHUB_AW_WORKFLOW_NAME || "Workflow"; if (eventName === "discussion") { @@ -646,7 +643,7 @@ jobs: } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); core.warning( - "Failed to add/edit comment with workflow link (This is not critical - the reaction was still added successfully): " + errorMessage + "Failed to create comment with workflow link (This is not critical - the reaction was still added successfully): " + errorMessage ); } } diff --git a/.github/workflows/changeset-generator.lock.yml b/.github/workflows/changeset-generator.lock.yml index 973e233aaaf..61a47836ba4 100644 --- a/.github/workflows/changeset-generator.lock.yml +++ b/.github/workflows/changeset-generator.lock.yml @@ -348,7 +348,7 @@ jobs: } let reactionEndpoint; let commentUpdateEndpoint; - let shouldEditComment = false; + let shouldCreateComment = false; const eventName = context.eventName; const owner = context.repo.owner; const repo = context.repo.repo; @@ -362,7 +362,6 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/comments`; - shouldEditComment = true; break; case "issue_comment": const commentId = context.payload?.comment?.id; @@ -372,7 +371,7 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/comments/${commentId}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/comments/${commentId}`; - shouldEditComment = command ? true : false; + shouldCreateComment = command ? true : false; break; case "pull_request": const prNumber = context.payload?.pull_request?.number; @@ -382,7 +381,6 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/comments`; - shouldEditComment = true; break; case "pull_request_review_comment": const reviewCommentId = context.payload?.comment?.id; @@ -392,7 +390,7 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/pulls/comments/${reviewCommentId}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/pulls/comments/${reviewCommentId}`; - shouldEditComment = command ? true : false; + shouldCreateComment = command ? true : false; break; case "discussion": const discussionNumber = context.payload?.discussion?.number; @@ -403,7 +401,6 @@ jobs: const discussion = await getDiscussionId(owner, repo, discussionNumber); reactionEndpoint = discussion.id; commentUpdateEndpoint = `discussion:${discussionNumber}`; - shouldEditComment = true; break; case "discussion_comment": const discussionCommentNumber = context.payload?.discussion?.number; @@ -419,7 +416,7 @@ jobs: } reactionEndpoint = commentNodeId; commentUpdateEndpoint = `discussion_comment:${discussionCommentNumber}:${discussionCommentId}`; - shouldEditComment = command ? true : false; + shouldCreateComment = command ? true : false; break; default: core.setFailed(`Unsupported event type: ${eventName}`); @@ -432,20 +429,20 @@ jobs: } else { await addReaction(reactionEndpoint, reaction); } - if (shouldEditComment && commentUpdateEndpoint) { + if (shouldCreateComment && commentUpdateEndpoint) { core.info(`Comment endpoint: ${commentUpdateEndpoint}`); - await addOrEditCommentWithWorkflowLink(commentUpdateEndpoint, runUrl, eventName); + await addCommentWithWorkflowLink(commentUpdateEndpoint, runUrl, eventName); } else { if (!command && commentUpdateEndpoint) { - core.info("Skipping comment edit - only available for command workflows"); + core.info("Skipping comment creation - only available for command workflows"); } else { core.info(`Skipping comment for event type: ${eventName}`); } } } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); - core.error(`Failed to process reaction and comment edit: ${errorMessage}`); - core.setFailed(`Failed to process reaction and comment edit: ${errorMessage}`); + core.error(`Failed to process reaction and comment creation: ${errorMessage}`); + core.setFailed(`Failed to process reaction and comment creation: ${errorMessage}`); } } async function addReaction(endpoint, reaction) { @@ -528,7 +525,7 @@ jobs: } throw new Error(`Discussion comment node ID not found in event payload for comment ${commentId}`); } - async function addOrEditCommentWithWorkflowLink(endpoint, runUrl, eventName) { + async function addCommentWithWorkflowLink(endpoint, runUrl, eventName) { try { const workflowName = process.env.GITHUB_AW_WORKFLOW_NAME || "Workflow"; if (eventName === "discussion") { @@ -638,7 +635,7 @@ jobs: } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); core.warning( - "Failed to add/edit comment with workflow link (This is not critical - the reaction was still added successfully): " + errorMessage + "Failed to create comment with workflow link (This is not critical - the reaction was still added successfully): " + errorMessage ); } } diff --git a/.github/workflows/dev.lock.yml b/.github/workflows/dev.lock.yml index ec00dee3eff..89e95ff60ba 100644 --- a/.github/workflows/dev.lock.yml +++ b/.github/workflows/dev.lock.yml @@ -268,7 +268,7 @@ jobs: } let reactionEndpoint; let commentUpdateEndpoint; - let shouldEditComment = false; + let shouldCreateComment = false; const eventName = context.eventName; const owner = context.repo.owner; const repo = context.repo.repo; @@ -282,7 +282,6 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/comments`; - shouldEditComment = true; break; case "issue_comment": const commentId = context.payload?.comment?.id; @@ -292,7 +291,7 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/comments/${commentId}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/comments/${commentId}`; - shouldEditComment = command ? true : false; + shouldCreateComment = command ? true : false; break; case "pull_request": const prNumber = context.payload?.pull_request?.number; @@ -302,7 +301,6 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/comments`; - shouldEditComment = true; break; case "pull_request_review_comment": const reviewCommentId = context.payload?.comment?.id; @@ -312,7 +310,7 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/pulls/comments/${reviewCommentId}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/pulls/comments/${reviewCommentId}`; - shouldEditComment = command ? true : false; + shouldCreateComment = command ? true : false; break; case "discussion": const discussionNumber = context.payload?.discussion?.number; @@ -323,7 +321,6 @@ jobs: const discussion = await getDiscussionId(owner, repo, discussionNumber); reactionEndpoint = discussion.id; commentUpdateEndpoint = `discussion:${discussionNumber}`; - shouldEditComment = true; break; case "discussion_comment": const discussionCommentNumber = context.payload?.discussion?.number; @@ -339,7 +336,7 @@ jobs: } reactionEndpoint = commentNodeId; commentUpdateEndpoint = `discussion_comment:${discussionCommentNumber}:${discussionCommentId}`; - shouldEditComment = command ? true : false; + shouldCreateComment = command ? true : false; break; default: core.setFailed(`Unsupported event type: ${eventName}`); @@ -352,20 +349,20 @@ jobs: } else { await addReaction(reactionEndpoint, reaction); } - if (shouldEditComment && commentUpdateEndpoint) { + if (shouldCreateComment && commentUpdateEndpoint) { core.info(`Comment endpoint: ${commentUpdateEndpoint}`); - await addOrEditCommentWithWorkflowLink(commentUpdateEndpoint, runUrl, eventName); + await addCommentWithWorkflowLink(commentUpdateEndpoint, runUrl, eventName); } else { if (!command && commentUpdateEndpoint) { - core.info("Skipping comment edit - only available for command workflows"); + core.info("Skipping comment creation - only available for command workflows"); } else { core.info(`Skipping comment for event type: ${eventName}`); } } } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); - core.error(`Failed to process reaction and comment edit: ${errorMessage}`); - core.setFailed(`Failed to process reaction and comment edit: ${errorMessage}`); + core.error(`Failed to process reaction and comment creation: ${errorMessage}`); + core.setFailed(`Failed to process reaction and comment creation: ${errorMessage}`); } } async function addReaction(endpoint, reaction) { @@ -448,7 +445,7 @@ jobs: } throw new Error(`Discussion comment node ID not found in event payload for comment ${commentId}`); } - async function addOrEditCommentWithWorkflowLink(endpoint, runUrl, eventName) { + async function addCommentWithWorkflowLink(endpoint, runUrl, eventName) { try { const workflowName = process.env.GITHUB_AW_WORKFLOW_NAME || "Workflow"; if (eventName === "discussion") { @@ -558,7 +555,7 @@ jobs: } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); core.warning( - "Failed to add/edit comment with workflow link (This is not critical - the reaction was still added successfully): " + errorMessage + "Failed to create comment with workflow link (This is not critical - the reaction was still added successfully): " + errorMessage ); } } diff --git a/.github/workflows/issue-classifier.lock.yml b/.github/workflows/issue-classifier.lock.yml index aecbb1d663f..79003acb4f2 100644 --- a/.github/workflows/issue-classifier.lock.yml +++ b/.github/workflows/issue-classifier.lock.yml @@ -345,7 +345,7 @@ jobs: } let reactionEndpoint; let commentUpdateEndpoint; - let shouldEditComment = false; + let shouldCreateComment = false; const eventName = context.eventName; const owner = context.repo.owner; const repo = context.repo.repo; @@ -359,7 +359,6 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/comments`; - shouldEditComment = true; break; case "issue_comment": const commentId = context.payload?.comment?.id; @@ -369,7 +368,7 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/comments/${commentId}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/comments/${commentId}`; - shouldEditComment = command ? true : false; + shouldCreateComment = command ? true : false; break; case "pull_request": const prNumber = context.payload?.pull_request?.number; @@ -379,7 +378,6 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/comments`; - shouldEditComment = true; break; case "pull_request_review_comment": const reviewCommentId = context.payload?.comment?.id; @@ -389,7 +387,7 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/pulls/comments/${reviewCommentId}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/pulls/comments/${reviewCommentId}`; - shouldEditComment = command ? true : false; + shouldCreateComment = command ? true : false; break; case "discussion": const discussionNumber = context.payload?.discussion?.number; @@ -400,7 +398,6 @@ jobs: const discussion = await getDiscussionId(owner, repo, discussionNumber); reactionEndpoint = discussion.id; commentUpdateEndpoint = `discussion:${discussionNumber}`; - shouldEditComment = true; break; case "discussion_comment": const discussionCommentNumber = context.payload?.discussion?.number; @@ -416,7 +413,7 @@ jobs: } reactionEndpoint = commentNodeId; commentUpdateEndpoint = `discussion_comment:${discussionCommentNumber}:${discussionCommentId}`; - shouldEditComment = command ? true : false; + shouldCreateComment = command ? true : false; break; default: core.setFailed(`Unsupported event type: ${eventName}`); @@ -429,20 +426,20 @@ jobs: } else { await addReaction(reactionEndpoint, reaction); } - if (shouldEditComment && commentUpdateEndpoint) { + if (shouldCreateComment && commentUpdateEndpoint) { core.info(`Comment endpoint: ${commentUpdateEndpoint}`); - await addOrEditCommentWithWorkflowLink(commentUpdateEndpoint, runUrl, eventName); + await addCommentWithWorkflowLink(commentUpdateEndpoint, runUrl, eventName); } else { if (!command && commentUpdateEndpoint) { - core.info("Skipping comment edit - only available for command workflows"); + core.info("Skipping comment creation - only available for command workflows"); } else { core.info(`Skipping comment for event type: ${eventName}`); } } } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); - core.error(`Failed to process reaction and comment edit: ${errorMessage}`); - core.setFailed(`Failed to process reaction and comment edit: ${errorMessage}`); + core.error(`Failed to process reaction and comment creation: ${errorMessage}`); + core.setFailed(`Failed to process reaction and comment creation: ${errorMessage}`); } } async function addReaction(endpoint, reaction) { @@ -525,7 +522,7 @@ jobs: } throw new Error(`Discussion comment node ID not found in event payload for comment ${commentId}`); } - async function addOrEditCommentWithWorkflowLink(endpoint, runUrl, eventName) { + async function addCommentWithWorkflowLink(endpoint, runUrl, eventName) { try { const workflowName = process.env.GITHUB_AW_WORKFLOW_NAME || "Workflow"; if (eventName === "discussion") { @@ -635,7 +632,7 @@ jobs: } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); core.warning( - "Failed to add/edit comment with workflow link (This is not critical - the reaction was still added successfully): " + errorMessage + "Failed to create comment with workflow link (This is not critical - the reaction was still added successfully): " + errorMessage ); } } diff --git a/.github/workflows/pdf-summary.lock.yml b/.github/workflows/pdf-summary.lock.yml index 5e51b548e1f..4873a56fcd1 100644 --- a/.github/workflows/pdf-summary.lock.yml +++ b/.github/workflows/pdf-summary.lock.yml @@ -377,7 +377,7 @@ jobs: } let reactionEndpoint; let commentUpdateEndpoint; - let shouldEditComment = false; + let shouldCreateComment = false; const eventName = context.eventName; const owner = context.repo.owner; const repo = context.repo.repo; @@ -391,7 +391,6 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/comments`; - shouldEditComment = true; break; case "issue_comment": const commentId = context.payload?.comment?.id; @@ -401,7 +400,7 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/comments/${commentId}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/comments/${commentId}`; - shouldEditComment = command ? true : false; + shouldCreateComment = command ? true : false; break; case "pull_request": const prNumber = context.payload?.pull_request?.number; @@ -411,7 +410,6 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/comments`; - shouldEditComment = true; break; case "pull_request_review_comment": const reviewCommentId = context.payload?.comment?.id; @@ -421,7 +419,7 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/pulls/comments/${reviewCommentId}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/pulls/comments/${reviewCommentId}`; - shouldEditComment = command ? true : false; + shouldCreateComment = command ? true : false; break; case "discussion": const discussionNumber = context.payload?.discussion?.number; @@ -432,7 +430,6 @@ jobs: const discussion = await getDiscussionId(owner, repo, discussionNumber); reactionEndpoint = discussion.id; commentUpdateEndpoint = `discussion:${discussionNumber}`; - shouldEditComment = true; break; case "discussion_comment": const discussionCommentNumber = context.payload?.discussion?.number; @@ -448,7 +445,7 @@ jobs: } reactionEndpoint = commentNodeId; commentUpdateEndpoint = `discussion_comment:${discussionCommentNumber}:${discussionCommentId}`; - shouldEditComment = command ? true : false; + shouldCreateComment = command ? true : false; break; default: core.setFailed(`Unsupported event type: ${eventName}`); @@ -461,20 +458,20 @@ jobs: } else { await addReaction(reactionEndpoint, reaction); } - if (shouldEditComment && commentUpdateEndpoint) { + if (shouldCreateComment && commentUpdateEndpoint) { core.info(`Comment endpoint: ${commentUpdateEndpoint}`); - await addOrEditCommentWithWorkflowLink(commentUpdateEndpoint, runUrl, eventName); + await addCommentWithWorkflowLink(commentUpdateEndpoint, runUrl, eventName); } else { if (!command && commentUpdateEndpoint) { - core.info("Skipping comment edit - only available for command workflows"); + core.info("Skipping comment creation - only available for command workflows"); } else { core.info(`Skipping comment for event type: ${eventName}`); } } } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); - core.error(`Failed to process reaction and comment edit: ${errorMessage}`); - core.setFailed(`Failed to process reaction and comment edit: ${errorMessage}`); + core.error(`Failed to process reaction and comment creation: ${errorMessage}`); + core.setFailed(`Failed to process reaction and comment creation: ${errorMessage}`); } } async function addReaction(endpoint, reaction) { @@ -557,7 +554,7 @@ jobs: } throw new Error(`Discussion comment node ID not found in event payload for comment ${commentId}`); } - async function addOrEditCommentWithWorkflowLink(endpoint, runUrl, eventName) { + async function addCommentWithWorkflowLink(endpoint, runUrl, eventName) { try { const workflowName = process.env.GITHUB_AW_WORKFLOW_NAME || "Workflow"; if (eventName === "discussion") { @@ -667,7 +664,7 @@ jobs: } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); core.warning( - "Failed to add/edit comment with workflow link (This is not critical - the reaction was still added successfully): " + errorMessage + "Failed to create comment with workflow link (This is not critical - the reaction was still added successfully): " + errorMessage ); } } diff --git a/.github/workflows/plan.lock.yml b/.github/workflows/plan.lock.yml index 91b66b56ff3..e6bdc76004b 100644 --- a/.github/workflows/plan.lock.yml +++ b/.github/workflows/plan.lock.yml @@ -347,7 +347,7 @@ jobs: } let reactionEndpoint; let commentUpdateEndpoint; - let shouldEditComment = false; + let shouldCreateComment = false; const eventName = context.eventName; const owner = context.repo.owner; const repo = context.repo.repo; @@ -361,7 +361,6 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/comments`; - shouldEditComment = true; break; case "issue_comment": const commentId = context.payload?.comment?.id; @@ -371,7 +370,7 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/comments/${commentId}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/comments/${commentId}`; - shouldEditComment = command ? true : false; + shouldCreateComment = command ? true : false; break; case "pull_request": const prNumber = context.payload?.pull_request?.number; @@ -381,7 +380,6 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/comments`; - shouldEditComment = true; break; case "pull_request_review_comment": const reviewCommentId = context.payload?.comment?.id; @@ -391,7 +389,7 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/pulls/comments/${reviewCommentId}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/pulls/comments/${reviewCommentId}`; - shouldEditComment = command ? true : false; + shouldCreateComment = command ? true : false; break; case "discussion": const discussionNumber = context.payload?.discussion?.number; @@ -402,7 +400,6 @@ jobs: const discussion = await getDiscussionId(owner, repo, discussionNumber); reactionEndpoint = discussion.id; commentUpdateEndpoint = `discussion:${discussionNumber}`; - shouldEditComment = true; break; case "discussion_comment": const discussionCommentNumber = context.payload?.discussion?.number; @@ -418,7 +415,7 @@ jobs: } reactionEndpoint = commentNodeId; commentUpdateEndpoint = `discussion_comment:${discussionCommentNumber}:${discussionCommentId}`; - shouldEditComment = command ? true : false; + shouldCreateComment = command ? true : false; break; default: core.setFailed(`Unsupported event type: ${eventName}`); @@ -431,20 +428,20 @@ jobs: } else { await addReaction(reactionEndpoint, reaction); } - if (shouldEditComment && commentUpdateEndpoint) { + if (shouldCreateComment && commentUpdateEndpoint) { core.info(`Comment endpoint: ${commentUpdateEndpoint}`); - await addOrEditCommentWithWorkflowLink(commentUpdateEndpoint, runUrl, eventName); + await addCommentWithWorkflowLink(commentUpdateEndpoint, runUrl, eventName); } else { if (!command && commentUpdateEndpoint) { - core.info("Skipping comment edit - only available for command workflows"); + core.info("Skipping comment creation - only available for command workflows"); } else { core.info(`Skipping comment for event type: ${eventName}`); } } } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); - core.error(`Failed to process reaction and comment edit: ${errorMessage}`); - core.setFailed(`Failed to process reaction and comment edit: ${errorMessage}`); + core.error(`Failed to process reaction and comment creation: ${errorMessage}`); + core.setFailed(`Failed to process reaction and comment creation: ${errorMessage}`); } } async function addReaction(endpoint, reaction) { @@ -527,7 +524,7 @@ jobs: } throw new Error(`Discussion comment node ID not found in event payload for comment ${commentId}`); } - async function addOrEditCommentWithWorkflowLink(endpoint, runUrl, eventName) { + async function addCommentWithWorkflowLink(endpoint, runUrl, eventName) { try { const workflowName = process.env.GITHUB_AW_WORKFLOW_NAME || "Workflow"; if (eventName === "discussion") { @@ -637,7 +634,7 @@ jobs: } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); core.warning( - "Failed to add/edit comment with workflow link (This is not critical - the reaction was still added successfully): " + errorMessage + "Failed to create comment with workflow link (This is not critical - the reaction was still added successfully): " + errorMessage ); } } diff --git a/.github/workflows/poem-bot.lock.yml b/.github/workflows/poem-bot.lock.yml index cfba46ec886..80947f047e9 100644 --- a/.github/workflows/poem-bot.lock.yml +++ b/.github/workflows/poem-bot.lock.yml @@ -388,7 +388,7 @@ jobs: } let reactionEndpoint; let commentUpdateEndpoint; - let shouldEditComment = false; + let shouldCreateComment = false; const eventName = context.eventName; const owner = context.repo.owner; const repo = context.repo.repo; @@ -402,7 +402,6 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/comments`; - shouldEditComment = true; break; case "issue_comment": const commentId = context.payload?.comment?.id; @@ -412,7 +411,7 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/comments/${commentId}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/comments/${commentId}`; - shouldEditComment = command ? true : false; + shouldCreateComment = command ? true : false; break; case "pull_request": const prNumber = context.payload?.pull_request?.number; @@ -422,7 +421,6 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/comments`; - shouldEditComment = true; break; case "pull_request_review_comment": const reviewCommentId = context.payload?.comment?.id; @@ -432,7 +430,7 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/pulls/comments/${reviewCommentId}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/pulls/comments/${reviewCommentId}`; - shouldEditComment = command ? true : false; + shouldCreateComment = command ? true : false; break; case "discussion": const discussionNumber = context.payload?.discussion?.number; @@ -443,7 +441,6 @@ jobs: const discussion = await getDiscussionId(owner, repo, discussionNumber); reactionEndpoint = discussion.id; commentUpdateEndpoint = `discussion:${discussionNumber}`; - shouldEditComment = true; break; case "discussion_comment": const discussionCommentNumber = context.payload?.discussion?.number; @@ -459,7 +456,7 @@ jobs: } reactionEndpoint = commentNodeId; commentUpdateEndpoint = `discussion_comment:${discussionCommentNumber}:${discussionCommentId}`; - shouldEditComment = command ? true : false; + shouldCreateComment = command ? true : false; break; default: core.setFailed(`Unsupported event type: ${eventName}`); @@ -472,20 +469,20 @@ jobs: } else { await addReaction(reactionEndpoint, reaction); } - if (shouldEditComment && commentUpdateEndpoint) { + if (shouldCreateComment && commentUpdateEndpoint) { core.info(`Comment endpoint: ${commentUpdateEndpoint}`); - await addOrEditCommentWithWorkflowLink(commentUpdateEndpoint, runUrl, eventName); + await addCommentWithWorkflowLink(commentUpdateEndpoint, runUrl, eventName); } else { if (!command && commentUpdateEndpoint) { - core.info("Skipping comment edit - only available for command workflows"); + core.info("Skipping comment creation - only available for command workflows"); } else { core.info(`Skipping comment for event type: ${eventName}`); } } } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); - core.error(`Failed to process reaction and comment edit: ${errorMessage}`); - core.setFailed(`Failed to process reaction and comment edit: ${errorMessage}`); + core.error(`Failed to process reaction and comment creation: ${errorMessage}`); + core.setFailed(`Failed to process reaction and comment creation: ${errorMessage}`); } } async function addReaction(endpoint, reaction) { @@ -568,7 +565,7 @@ jobs: } throw new Error(`Discussion comment node ID not found in event payload for comment ${commentId}`); } - async function addOrEditCommentWithWorkflowLink(endpoint, runUrl, eventName) { + async function addCommentWithWorkflowLink(endpoint, runUrl, eventName) { try { const workflowName = process.env.GITHUB_AW_WORKFLOW_NAME || "Workflow"; if (eventName === "discussion") { @@ -678,7 +675,7 @@ jobs: } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); core.warning( - "Failed to add/edit comment with workflow link (This is not critical - the reaction was still added successfully): " + errorMessage + "Failed to create comment with workflow link (This is not critical - the reaction was still added successfully): " + errorMessage ); } } diff --git a/.github/workflows/q.lock.yml b/.github/workflows/q.lock.yml index f80c3c03cac..8396a721f24 100644 --- a/.github/workflows/q.lock.yml +++ b/.github/workflows/q.lock.yml @@ -399,7 +399,7 @@ jobs: } let reactionEndpoint; let commentUpdateEndpoint; - let shouldEditComment = false; + let shouldCreateComment = false; const eventName = context.eventName; const owner = context.repo.owner; const repo = context.repo.repo; @@ -413,7 +413,6 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/comments`; - shouldEditComment = true; break; case "issue_comment": const commentId = context.payload?.comment?.id; @@ -423,7 +422,7 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/comments/${commentId}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/comments/${commentId}`; - shouldEditComment = command ? true : false; + shouldCreateComment = command ? true : false; break; case "pull_request": const prNumber = context.payload?.pull_request?.number; @@ -433,7 +432,6 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/comments`; - shouldEditComment = true; break; case "pull_request_review_comment": const reviewCommentId = context.payload?.comment?.id; @@ -443,7 +441,7 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/pulls/comments/${reviewCommentId}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/pulls/comments/${reviewCommentId}`; - shouldEditComment = command ? true : false; + shouldCreateComment = command ? true : false; break; case "discussion": const discussionNumber = context.payload?.discussion?.number; @@ -454,7 +452,6 @@ jobs: const discussion = await getDiscussionId(owner, repo, discussionNumber); reactionEndpoint = discussion.id; commentUpdateEndpoint = `discussion:${discussionNumber}`; - shouldEditComment = true; break; case "discussion_comment": const discussionCommentNumber = context.payload?.discussion?.number; @@ -470,7 +467,7 @@ jobs: } reactionEndpoint = commentNodeId; commentUpdateEndpoint = `discussion_comment:${discussionCommentNumber}:${discussionCommentId}`; - shouldEditComment = command ? true : false; + shouldCreateComment = command ? true : false; break; default: core.setFailed(`Unsupported event type: ${eventName}`); @@ -483,20 +480,20 @@ jobs: } else { await addReaction(reactionEndpoint, reaction); } - if (shouldEditComment && commentUpdateEndpoint) { + if (shouldCreateComment && commentUpdateEndpoint) { core.info(`Comment endpoint: ${commentUpdateEndpoint}`); - await addOrEditCommentWithWorkflowLink(commentUpdateEndpoint, runUrl, eventName); + await addCommentWithWorkflowLink(commentUpdateEndpoint, runUrl, eventName); } else { if (!command && commentUpdateEndpoint) { - core.info("Skipping comment edit - only available for command workflows"); + core.info("Skipping comment creation - only available for command workflows"); } else { core.info(`Skipping comment for event type: ${eventName}`); } } } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); - core.error(`Failed to process reaction and comment edit: ${errorMessage}`); - core.setFailed(`Failed to process reaction and comment edit: ${errorMessage}`); + core.error(`Failed to process reaction and comment creation: ${errorMessage}`); + core.setFailed(`Failed to process reaction and comment creation: ${errorMessage}`); } } async function addReaction(endpoint, reaction) { @@ -579,7 +576,7 @@ jobs: } throw new Error(`Discussion comment node ID not found in event payload for comment ${commentId}`); } - async function addOrEditCommentWithWorkflowLink(endpoint, runUrl, eventName) { + async function addCommentWithWorkflowLink(endpoint, runUrl, eventName) { try { const workflowName = process.env.GITHUB_AW_WORKFLOW_NAME || "Workflow"; if (eventName === "discussion") { @@ -689,7 +686,7 @@ jobs: } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); core.warning( - "Failed to add/edit comment with workflow link (This is not critical - the reaction was still added successfully): " + errorMessage + "Failed to create comment with workflow link (This is not critical - the reaction was still added successfully): " + errorMessage ); } } diff --git a/.github/workflows/scout.lock.yml b/.github/workflows/scout.lock.yml index dd7803feb7b..7f403e768df 100644 --- a/.github/workflows/scout.lock.yml +++ b/.github/workflows/scout.lock.yml @@ -411,7 +411,7 @@ jobs: } let reactionEndpoint; let commentUpdateEndpoint; - let shouldEditComment = false; + let shouldCreateComment = false; const eventName = context.eventName; const owner = context.repo.owner; const repo = context.repo.repo; @@ -425,7 +425,6 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/comments`; - shouldEditComment = true; break; case "issue_comment": const commentId = context.payload?.comment?.id; @@ -435,7 +434,7 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/comments/${commentId}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/comments/${commentId}`; - shouldEditComment = command ? true : false; + shouldCreateComment = command ? true : false; break; case "pull_request": const prNumber = context.payload?.pull_request?.number; @@ -445,7 +444,6 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/comments`; - shouldEditComment = true; break; case "pull_request_review_comment": const reviewCommentId = context.payload?.comment?.id; @@ -455,7 +453,7 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/pulls/comments/${reviewCommentId}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/pulls/comments/${reviewCommentId}`; - shouldEditComment = command ? true : false; + shouldCreateComment = command ? true : false; break; case "discussion": const discussionNumber = context.payload?.discussion?.number; @@ -466,7 +464,6 @@ jobs: const discussion = await getDiscussionId(owner, repo, discussionNumber); reactionEndpoint = discussion.id; commentUpdateEndpoint = `discussion:${discussionNumber}`; - shouldEditComment = true; break; case "discussion_comment": const discussionCommentNumber = context.payload?.discussion?.number; @@ -482,7 +479,7 @@ jobs: } reactionEndpoint = commentNodeId; commentUpdateEndpoint = `discussion_comment:${discussionCommentNumber}:${discussionCommentId}`; - shouldEditComment = command ? true : false; + shouldCreateComment = command ? true : false; break; default: core.setFailed(`Unsupported event type: ${eventName}`); @@ -495,20 +492,20 @@ jobs: } else { await addReaction(reactionEndpoint, reaction); } - if (shouldEditComment && commentUpdateEndpoint) { + if (shouldCreateComment && commentUpdateEndpoint) { core.info(`Comment endpoint: ${commentUpdateEndpoint}`); - await addOrEditCommentWithWorkflowLink(commentUpdateEndpoint, runUrl, eventName); + await addCommentWithWorkflowLink(commentUpdateEndpoint, runUrl, eventName); } else { if (!command && commentUpdateEndpoint) { - core.info("Skipping comment edit - only available for command workflows"); + core.info("Skipping comment creation - only available for command workflows"); } else { core.info(`Skipping comment for event type: ${eventName}`); } } } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); - core.error(`Failed to process reaction and comment edit: ${errorMessage}`); - core.setFailed(`Failed to process reaction and comment edit: ${errorMessage}`); + core.error(`Failed to process reaction and comment creation: ${errorMessage}`); + core.setFailed(`Failed to process reaction and comment creation: ${errorMessage}`); } } async function addReaction(endpoint, reaction) { @@ -591,7 +588,7 @@ jobs: } throw new Error(`Discussion comment node ID not found in event payload for comment ${commentId}`); } - async function addOrEditCommentWithWorkflowLink(endpoint, runUrl, eventName) { + async function addCommentWithWorkflowLink(endpoint, runUrl, eventName) { try { const workflowName = process.env.GITHUB_AW_WORKFLOW_NAME || "Workflow"; if (eventName === "discussion") { @@ -701,7 +698,7 @@ jobs: } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); core.warning( - "Failed to add/edit comment with workflow link (This is not critical - the reaction was still added successfully): " + errorMessage + "Failed to create comment with workflow link (This is not critical - the reaction was still added successfully): " + errorMessage ); } } diff --git a/.github/workflows/tidy.lock.yml b/.github/workflows/tidy.lock.yml index 84fb4aff849..d3889cd61d2 100644 --- a/.github/workflows/tidy.lock.yml +++ b/.github/workflows/tidy.lock.yml @@ -198,7 +198,7 @@ jobs: } let reactionEndpoint; let commentUpdateEndpoint; - let shouldEditComment = false; + let shouldCreateComment = false; const eventName = context.eventName; const owner = context.repo.owner; const repo = context.repo.repo; @@ -212,7 +212,6 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/comments`; - shouldEditComment = true; break; case "issue_comment": const commentId = context.payload?.comment?.id; @@ -222,7 +221,7 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/comments/${commentId}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/comments/${commentId}`; - shouldEditComment = command ? true : false; + shouldCreateComment = command ? true : false; break; case "pull_request": const prNumber = context.payload?.pull_request?.number; @@ -232,7 +231,6 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/comments`; - shouldEditComment = true; break; case "pull_request_review_comment": const reviewCommentId = context.payload?.comment?.id; @@ -242,7 +240,7 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/pulls/comments/${reviewCommentId}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/pulls/comments/${reviewCommentId}`; - shouldEditComment = command ? true : false; + shouldCreateComment = command ? true : false; break; case "discussion": const discussionNumber = context.payload?.discussion?.number; @@ -253,7 +251,6 @@ jobs: const discussion = await getDiscussionId(owner, repo, discussionNumber); reactionEndpoint = discussion.id; commentUpdateEndpoint = `discussion:${discussionNumber}`; - shouldEditComment = true; break; case "discussion_comment": const discussionCommentNumber = context.payload?.discussion?.number; @@ -269,7 +266,7 @@ jobs: } reactionEndpoint = commentNodeId; commentUpdateEndpoint = `discussion_comment:${discussionCommentNumber}:${discussionCommentId}`; - shouldEditComment = command ? true : false; + shouldCreateComment = command ? true : false; break; default: core.setFailed(`Unsupported event type: ${eventName}`); @@ -282,20 +279,20 @@ jobs: } else { await addReaction(reactionEndpoint, reaction); } - if (shouldEditComment && commentUpdateEndpoint) { + if (shouldCreateComment && commentUpdateEndpoint) { core.info(`Comment endpoint: ${commentUpdateEndpoint}`); - await addOrEditCommentWithWorkflowLink(commentUpdateEndpoint, runUrl, eventName); + await addCommentWithWorkflowLink(commentUpdateEndpoint, runUrl, eventName); } else { if (!command && commentUpdateEndpoint) { - core.info("Skipping comment edit - only available for command workflows"); + core.info("Skipping comment creation - only available for command workflows"); } else { core.info(`Skipping comment for event type: ${eventName}`); } } } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); - core.error(`Failed to process reaction and comment edit: ${errorMessage}`); - core.setFailed(`Failed to process reaction and comment edit: ${errorMessage}`); + core.error(`Failed to process reaction and comment creation: ${errorMessage}`); + core.setFailed(`Failed to process reaction and comment creation: ${errorMessage}`); } } async function addReaction(endpoint, reaction) { @@ -378,7 +375,7 @@ jobs: } throw new Error(`Discussion comment node ID not found in event payload for comment ${commentId}`); } - async function addOrEditCommentWithWorkflowLink(endpoint, runUrl, eventName) { + async function addCommentWithWorkflowLink(endpoint, runUrl, eventName) { try { const workflowName = process.env.GITHUB_AW_WORKFLOW_NAME || "Workflow"; if (eventName === "discussion") { @@ -488,7 +485,7 @@ jobs: } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); core.warning( - "Failed to add/edit comment with workflow link (This is not critical - the reaction was still added successfully): " + errorMessage + "Failed to create comment with workflow link (This is not critical - the reaction was still added successfully): " + errorMessage ); } } diff --git a/.github/workflows/unbloat-docs.lock.yml b/.github/workflows/unbloat-docs.lock.yml index 5d9430ff3ce..29fc80f22f6 100644 --- a/.github/workflows/unbloat-docs.lock.yml +++ b/.github/workflows/unbloat-docs.lock.yml @@ -202,7 +202,7 @@ jobs: } let reactionEndpoint; let commentUpdateEndpoint; - let shouldEditComment = false; + let shouldCreateComment = false; const eventName = context.eventName; const owner = context.repo.owner; const repo = context.repo.repo; @@ -216,7 +216,6 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${issueNumber}/comments`; - shouldEditComment = true; break; case "issue_comment": const commentId = context.payload?.comment?.id; @@ -226,7 +225,7 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/comments/${commentId}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/comments/${commentId}`; - shouldEditComment = command ? true : false; + shouldCreateComment = command ? true : false; break; case "pull_request": const prNumber = context.payload?.pull_request?.number; @@ -236,7 +235,6 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${prNumber}/comments`; - shouldEditComment = true; break; case "pull_request_review_comment": const reviewCommentId = context.payload?.comment?.id; @@ -246,7 +244,7 @@ jobs: } reactionEndpoint = `/repos/${owner}/${repo}/pulls/comments/${reviewCommentId}/reactions`; commentUpdateEndpoint = `/repos/${owner}/${repo}/pulls/comments/${reviewCommentId}`; - shouldEditComment = command ? true : false; + shouldCreateComment = command ? true : false; break; case "discussion": const discussionNumber = context.payload?.discussion?.number; @@ -257,7 +255,6 @@ jobs: const discussion = await getDiscussionId(owner, repo, discussionNumber); reactionEndpoint = discussion.id; commentUpdateEndpoint = `discussion:${discussionNumber}`; - shouldEditComment = true; break; case "discussion_comment": const discussionCommentNumber = context.payload?.discussion?.number; @@ -273,7 +270,7 @@ jobs: } reactionEndpoint = commentNodeId; commentUpdateEndpoint = `discussion_comment:${discussionCommentNumber}:${discussionCommentId}`; - shouldEditComment = command ? true : false; + shouldCreateComment = command ? true : false; break; default: core.setFailed(`Unsupported event type: ${eventName}`); @@ -286,20 +283,20 @@ jobs: } else { await addReaction(reactionEndpoint, reaction); } - if (shouldEditComment && commentUpdateEndpoint) { + if (shouldCreateComment && commentUpdateEndpoint) { core.info(`Comment endpoint: ${commentUpdateEndpoint}`); - await addOrEditCommentWithWorkflowLink(commentUpdateEndpoint, runUrl, eventName); + await addCommentWithWorkflowLink(commentUpdateEndpoint, runUrl, eventName); } else { if (!command && commentUpdateEndpoint) { - core.info("Skipping comment edit - only available for command workflows"); + core.info("Skipping comment creation - only available for command workflows"); } else { core.info(`Skipping comment for event type: ${eventName}`); } } } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); - core.error(`Failed to process reaction and comment edit: ${errorMessage}`); - core.setFailed(`Failed to process reaction and comment edit: ${errorMessage}`); + core.error(`Failed to process reaction and comment creation: ${errorMessage}`); + core.setFailed(`Failed to process reaction and comment creation: ${errorMessage}`); } } async function addReaction(endpoint, reaction) { @@ -382,7 +379,7 @@ jobs: } throw new Error(`Discussion comment node ID not found in event payload for comment ${commentId}`); } - async function addOrEditCommentWithWorkflowLink(endpoint, runUrl, eventName) { + async function addCommentWithWorkflowLink(endpoint, runUrl, eventName) { try { const workflowName = process.env.GITHUB_AW_WORKFLOW_NAME || "Workflow"; if (eventName === "discussion") { @@ -492,7 +489,7 @@ jobs: } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); core.warning( - "Failed to add/edit comment with workflow link (This is not critical - the reaction was still added successfully): " + errorMessage + "Failed to create comment with workflow link (This is not critical - the reaction was still added successfully): " + errorMessage ); } } diff --git a/pkg/workflow/js/add_reaction_and_edit_comment.cjs b/pkg/workflow/js/add_reaction_and_edit_comment.cjs index ab7a82c9994..d696aa55215 100644 --- a/pkg/workflow/js/add_reaction_and_edit_comment.cjs +++ b/pkg/workflow/js/add_reaction_and_edit_comment.cjs @@ -42,12 +42,18 @@ async function main() { case "issue_comment": const commentId = context.payload?.comment?.id; + const issueNumberForComment = context.payload?.issue?.number; if (!commentId) { core.setFailed("Comment ID not found in event payload"); return; } + if (!issueNumberForComment) { + core.setFailed("Issue number not found in event payload"); + return; + } reactionEndpoint = `/repos/${owner}/${repo}/issues/comments/${commentId}/reactions`; - commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/comments/${commentId}`; + // Create new comment on the issue itself, not on the comment + commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${issueNumberForComment}/comments`; // Only create comments for command workflows shouldCreateComment = command ? true : false; break; @@ -65,12 +71,18 @@ async function main() { case "pull_request_review_comment": const reviewCommentId = context.payload?.comment?.id; + const prNumberForReviewComment = context.payload?.pull_request?.number; if (!reviewCommentId) { core.setFailed("Review comment ID not found in event payload"); return; } + if (!prNumberForReviewComment) { + core.setFailed("Pull request number not found in event payload"); + return; + } reactionEndpoint = `/repos/${owner}/${repo}/pulls/comments/${reviewCommentId}/reactions`; - commentUpdateEndpoint = `/repos/${owner}/${repo}/pulls/comments/${reviewCommentId}`; + // Create new comment on the PR itself (using issues endpoint since PRs are issues) + commentUpdateEndpoint = `/repos/${owner}/${repo}/issues/${prNumberForReviewComment}/comments`; // Only create comments for command workflows shouldCreateComment = command ? true : false; break; diff --git a/pkg/workflow/js/add_reaction_and_edit_comment.test.cjs b/pkg/workflow/js/add_reaction_and_edit_comment.test.cjs index 97c3a2b0c1c..0bf03f02671 100644 --- a/pkg/workflow/js/add_reaction_and_edit_comment.test.cjs +++ b/pkg/workflow/js/add_reaction_and_edit_comment.test.cjs @@ -394,17 +394,17 @@ describe("add_reaction_and_edit_comment.cjs", () => { // Execute the script await eval(`(async () => { ${reactionScript} })()`); - // Verify new comment was created, NOT edited - // Should be POST to comments endpoint, not GET then PATCH to specific comment + // Verify new comment was created on the issue, NOT on the comment + // Should be POST to issue comments endpoint, not to the specific comment expect(mockGithub.request).toHaveBeenCalledWith( - "POST /repos/testowner/testrepo/issues/comments/456", + "POST /repos/testowner/testrepo/issues/123/comments", expect.objectContaining({ body: expect.stringContaining("Agentic [Test Workflow]"), }) ); - // Verify GET (for editing) was NOT called - expect(mockGithub.request).not.toHaveBeenCalledWith("GET /repos/testowner/testrepo/issues/comments/456", expect.anything()); + // Verify we're not posting to the comment endpoint (which would be wrong) + expect(mockGithub.request).not.toHaveBeenCalledWith("POST /repos/testowner/testrepo/issues/comments/456", expect.anything()); // Verify outputs expect(mockCore.setOutput).toHaveBeenCalledWith("comment-id", "789"); @@ -436,16 +436,17 @@ describe("add_reaction_and_edit_comment.cjs", () => { // Execute the script await eval(`(async () => { ${reactionScript} })()`); - // Verify new comment was created + // Verify new comment was created on the PR, NOT on the review comment + // Should be POST to PR (issues) comments endpoint, not to the specific review comment expect(mockGithub.request).toHaveBeenCalledWith( - "POST /repos/testowner/testrepo/pulls/comments/789", + "POST /repos/testowner/testrepo/issues/456/comments", expect.objectContaining({ body: expect.stringContaining("Agentic [PR Review Bot]"), }) ); - // Verify GET (for editing) was NOT called - expect(mockGithub.request).not.toHaveBeenCalledWith("GET /repos/testowner/testrepo/pulls/comments/789", expect.anything()); + // Verify we're not posting to the review comment endpoint (which would be wrong) + expect(mockGithub.request).not.toHaveBeenCalledWith("POST /repos/testowner/testrepo/pulls/comments/789", expect.anything()); // Verify outputs expect(mockCore.setOutput).toHaveBeenCalledWith("comment-id", "999");