From b7a09856e04951a89196d68b7f36e12c8f843061 Mon Sep 17 00:00:00 2001 From: Kosinkadink Date: Fri, 15 May 2026 22:52:17 -0700 Subject: [PATCH] fix: address CodeRabbit findings on cut-release.yml - approval gate now honors latest review state per reviewer; a reviewer who later submits CHANGES_REQUESTED or has their approval dismissed no longer counts as approved. Plain COMMENTED follow-ups don't override an existing approval (matches GitHub's own behavior). - success summary links to the tag's tree URL instead of /releases/tag/, which would 404 because this workflow creates an annotated git tag, not a GitHub Release object. --- .github/workflows/cut-release.yml | 37 ++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/.github/workflows/cut-release.yml b/.github/workflows/cut-release.yml index 9cad755c8..b7f55c71e 100644 --- a/.github/workflows/cut-release.yml +++ b/.github/workflows/cut-release.yml @@ -239,22 +239,35 @@ jobs: # * on the current HEAD (commit_id == PR_HEAD_SHA) — newer # commits invalidate older approvals. REVIEWS=$(gh api "repos/${REPO_FULL}/pulls/${PR_NUMBER}/reviews" --paginate) - # Normalize allow-list (split on comma, strip whitespace per - # field, lowercase, drop empties) and pick the first APPROVED - # review on the current head SHA from any of those users — all - # inside jq so we don't trip over login chars like `[bot]` that - # bash globbing/word-splitting would mishandle. + # Normalize allow-list and find an APPROVED review on the current + # head SHA, all inside jq so we don't trip over login chars like + # `[bot]` that bash globbing/word-splitting would mishandle. + # + # GitHub returns every review submission separately, so a reviewer + # who approved and then later submitted CHANGES_REQUESTED or had + # their approval dismissed will still have the old APPROVED entry + # in the list. To honor the *latest* state, filter to stateful + # reviews only (APPROVED / CHANGES_REQUESTED / DISMISSED — plain + # COMMENTED replies don't override an approval, matching GitHub's + # own behavior), group by reviewer, take each reviewer's last + # stateful submission, then accept if it's APPROVED. APPROVED_BY=$(echo "$REVIEWS" | jq -r --arg list "$APPROVERS" --arg sha "$PR_HEAD_SHA" ' ($list | split(",") | map(gsub("\\s"; "") | ascii_downcase) | map(select(length > 0)) ) as $allow - | [ .[] | select( - .state == "APPROVED" - and .commit_id == $sha - and (.user.login | ascii_downcase | IN($allow[])) - ) ] | .[0].user.login // "" + | [ .[] + | select(.commit_id == $sha) + | select(.user.login | ascii_downcase | IN($allow[])) + | select(.state == "APPROVED" + or .state == "CHANGES_REQUESTED" + or .state == "DISMISSED") + ] + | group_by(.user.login | ascii_downcase) + | map(sort_by(.submitted_at, .id) | last) + | map(select(.state == "APPROVED")) + | .[0].user.login // "" ') if [ -z "$APPROVED_BY" ]; then echo "::error::PR #${PR_NUMBER} has no APPROVED review on commit ${PR_HEAD_SHA:0:12} from a permitted approver. Allowed approvers: ${APPROVERS}." @@ -434,7 +447,9 @@ jobs: echo "✅ Created \`$NEXT_BRANCH\` and tagged \`$NEXT_TAG\` from \`$INPUT_SOURCE_BRANCH\` (with version bump)." echo "" echo "- Branch: " - echo "- Tag: " + # /releases/tag/ would 404 — this workflow creates an annotated + # git tag, not a GitHub Release object. + echo "- Tag: " echo "" echo "Next: run [release-stable-all.yml](https://github.com/${REPO_FULL}/actions/workflows/release-stable-all.yml) with \`git_tag=${NEXT_TAG}\`." fi