From 588d588786514e7cf734ae64b3eff7647acb9090 Mon Sep 17 00:00:00 2001 From: Mason McElvain <52104630+masonmcelvain@users.noreply.github.com> Date: Wed, 24 Jun 2026 13:08:53 -0700 Subject: [PATCH] fix: register GitHub approvals as CR on the webhook Webhooks use lowercase "approved", whereas the REST API uses uppercase "APPROVED". Webhook docs: - https://docs.github.com/en/webhooks/webhook-events-and-payloads#pull_request_review - https://github.com/octokit/webhooks/blob/3a58428aa5c399cf5aa12c8663aea1fb1f515254/payload-types/schema.d.ts#L6497 REST docs: - https://docs.github.com/en/rest/pulls/reviews?apiVersion=2026-03-10#list-reviews-for-a-pull-request Co-Authored-By: Claude Opus 4.8 (1M context) --- models/signature.js | 2 +- test/signature.test.js | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/models/signature.js b/models/signature.js index 17721ab7..1d926673 100644 --- a/models/signature.js +++ b/models/signature.js @@ -69,7 +69,7 @@ Signature.parseReview = function parseReview(review, repoFullName, pullNumber) { // `CR :emoji:` tag in the body. Skip if the body already produced one. if ( useGithubApprovalForCr() && - review.state === "APPROVED" && + review.state?.toUpperCase() === "APPROVED" && !signatures.some((sig) => sig.data.type === "CR") ) { signatures.push( diff --git a/test/signature.test.js b/test/signature.test.js index 87875f76..2658516c 100644 --- a/test/signature.test.js +++ b/test/signature.test.js @@ -31,6 +31,26 @@ test("parseReview creates CR signature from APPROVED review with empty body", () assert.equal(signatures[0].data.fromGithubApproval, true); }); +test("parseReview creates CR signature from lowercase webhook approved state", () => { + // The `pull_request_review` webhook sends `state: "approved"` (lowercase), + // unlike the REST API's `"APPROVED"`. Both must produce a CR signature. + const signatures = Signature.parseReview( + { + id: 103, + body: "", + state: "approved", + user: reviewUser, + submitted_at: "2024-01-01T00:00:00Z", + }, + repo, + number + ); + + assert.equal(signatures.length, 1); + assert.equal(signatures[0].data.type, "CR"); + assert.equal(signatures[0].data.fromGithubApproval, true); +}); + test("parseReview keeps single CR signature when body already contains CR tag", () => { const signatures = Signature.parseReview( {