diff --git a/actions/setup/js/dismiss_pull_request_review.cjs b/actions/setup/js/dismiss_pull_request_review.cjs index fa644a29413..1a72bf55b3f 100644 --- a/actions/setup/js/dismiss_pull_request_review.cjs +++ b/actions/setup/js/dismiss_pull_request_review.cjs @@ -225,12 +225,31 @@ async function main(config = {}) { }; } - const { data: review } = await githubClient.rest.pulls.getReview({ - owner, - repo, - pull_number: pullRequestNumber, - review_id: reviewId, - }); + let review; + try { + const { data } = await githubClient.rest.pulls.getReview({ + owner, + repo, + pull_number: pullRequestNumber, + review_id: reviewId, + }); + review = data; + } catch (getReviewError) { + if (getReviewError?.status === 404) { + return { + success: true, + skipped: true, + reason: "review no longer exists", + review_id: reviewId, + pull_request_number: pullRequestNumber, + repo: `${owner}/${repo}`, + }; + } + if (getReviewError && typeof getReviewError.message === "string") { + getReviewError.message = `Failed to fetch review ${reviewId} on ${owner}/${repo}#${pullRequestNumber}: ` + getReviewError.message; + } + throw getReviewError; + } const reviewAuthorLogin = review?.user?.login; const reviewAuthorType = typeof review?.user?.type === "string" ? review.user.type.trim() : ""; diff --git a/actions/setup/js/dismiss_pull_request_review.test.cjs b/actions/setup/js/dismiss_pull_request_review.test.cjs index 039665c7495..7d71200a9b2 100644 --- a/actions/setup/js/dismiss_pull_request_review.test.cjs +++ b/actions/setup/js/dismiss_pull_request_review.test.cjs @@ -365,4 +365,39 @@ describe("dismiss_pull_request_review", () => { expect(result.error).toContain("truncated"); expect(mockListReviews).toHaveBeenCalledTimes(10); }); + + it("returns skipped no-op when getReview returns 404 for an explicit review_id", async () => { + const notFoundError = Object.assign(new Error("Not Found"), { status: 404 }); + mockGetReview.mockRejectedValueOnce(notFoundError); + + const result = await handler({ + type: "dismiss_pull_request_review", + review_id: 123, + justification: "This stale review no longer reflects the updated implementation.", + }); + + expect(result.success).toBe(true); + expect(result.skipped).toBe(true); + expect(result.reason).toContain("review no longer exists"); + expect(result.review_id).toBe(123); + expect(result.pull_request_number).toBe(42); + expect(result.repo).toBe("test-owner/test-repo"); + expect(mockDismissReview).not.toHaveBeenCalled(); + }); + + it("fails with review context when getReview returns a non-404 error", async () => { + const serverError = Object.assign(new Error("Internal Server Error"), { status: 500 }); + mockGetReview.mockRejectedValueOnce(serverError); + + const result = await handler({ + type: "dismiss_pull_request_review", + review_id: 123, + justification: "This stale review no longer reflects the updated implementation.", + }); + + expect(result.success).toBe(false); + expect(result.error).toContain("Failed to fetch review 123 on test-owner/test-repo#42"); + expect(result.error).toContain("Internal Server Error"); + expect(mockDismissReview).not.toHaveBeenCalled(); + }); });