Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[
{
"user": {
"login": "coderabbitai[bot]"
},
"body": "<!-- This is an auto-generated comment: summarize by coderabbit.ai -->\n<!-- pre_merge_checks_walkthrough_start -->\n<summary>🚥 Pre-merge checks | ✅ 5</summary>\n<!-- pre_merge_checks_walkthrough_end -->",
"created_at": "2026-07-11T11:30:00Z"
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
[
{
"user": {
"login": "coderabbitai[bot]"
},
"state": "APPROVED",
"commit_id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"submitted_at": "2026-07-11T10:00:00Z",
"last_edited_at": "2026-07-11T12:00:00Z",
"body": "Approval body edited after the later verdict."
},
{
"user": {
"login": "coderabbitai[bot]"
},
"state": "CHANGES_REQUESTED",
"commit_id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"submitted_at": "2026-07-11T11:00:00Z",
"last_edited_at": null,
"body": "A later red verdict must remain authoritative."
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[
{
"user": {
"login": "coderabbitai[bot]"
},
"body": "<!-- This is an auto-generated comment: summarize by coderabbit.ai -->\n<!-- pre_merge_checks_walkthrough_start -->\n<summary>🚥 Pre-merge checks | ✅ 5</summary>\n<!-- pre_merge_checks_walkthrough_end -->",
"created_at": "2026-07-11T11:30:00Z"
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
[
{
"user": {
"login": "coderabbitai[bot]"
},
"state": "APPROVED",
"commit_id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"submitted_at": "2026-07-11T10:00:00Z",
"last_edited_at": "2026-07-11T12:00:00Z",
"body": "Approval body edited after the later dismissal."
},
{
"user": {
"login": "coderabbitai[bot]"
},
"state": "DISMISSED",
"commit_id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"submitted_at": "2026-07-11T11:00:00Z",
"last_edited_at": null,
"body": "A later dismissal must remain authoritative."
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[
{
"user": {
"login": "coderabbitai[bot]"
},
"body": "<!-- This is an auto-generated comment: summarize by coderabbit.ai -->\n<!-- pre_merge_checks_walkthrough_start -->\n<summary>🚥 Pre-merge checks | ✅ 5</summary>\n<!-- pre_merge_checks_walkthrough_end -->",
"created_at": "2026-07-11T11:30:00Z"
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
[
{
"user": {
"login": "coderabbitai[bot]"
},
"state": "CHANGES_REQUESTED",
"commit_id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"submitted_at": "2026-07-11T10:00:00Z",
"last_edited_at": "2026-07-11T12:00:00Z",
"body": "The older red verdict body was edited later."
},
{
"user": {
"login": "coderabbitai[bot]"
},
"state": "APPROVED",
"commit_id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"submitted_at": "2026-07-11T11:00:00Z",
"last_edited_at": null,
"body": "A later approval supersedes the earlier red verdict."
}
]
16 changes: 16 additions & 0 deletions .github/tests/merge-gate-fixtures/index.json
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,18 @@
"name": "cr-approval-superseded-at-head",
"expect_green": false
},
{
"name": "cr-approval-edited-after-changes-requested",
"expect_green": false
},
{
"name": "cr-approval-edited-after-dismissal",
"expect_green": false
},
{
"name": "cr-changes-requested-then-approval",
"expect_green": true
},
{
"name": "cr-approval-dismissed-at-head",
"expect_green": false
Expand Down Expand Up @@ -135,6 +147,10 @@
"name": "premerge-warning-full",
"expect_green": false
},
{
"name": "premerge-full-pass-only-in-explanation",
"expect_green": false
},
{
"name": "premerge-stale-before-head",
"expect_green": false
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[
{
"user": {
"login": "coderabbitai[bot]"
},
"body": "<!-- This is an auto-generated comment: summarize by coderabbit.ai -->\n<!-- pre_merge_checks_walkthrough_start -->\n## Pre-merge checks\n| Check | Status | Details |\n| --- | --- | --- |\n| Title check | ✅ Passed | Current result |\n| Linked Issues | Pending | Previous result: ✅ Passed |\n<!-- pre_merge_checks_walkthrough_end -->",
"created_at": "2026-07-11T10:00:00Z"
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[
{
"user": {
"login": "coderabbitai[bot]"
},
"state": "APPROVED",
"commit_id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"submitted_at": "2026-07-11T10:00:00Z"
}
]
29 changes: 19 additions & 10 deletions .scripts/check-merge-gates.sh
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,15 @@ premerge_state="not-posted"

# CodeRabbit's verdict at the head is its LATEST verdict-bearing review there:
# an APPROVED superseded by CHANGES_REQUESTED (or dismissed) must not count.
# Verdict chronology is submission chronology; editing an older review body
# must not make its verdict supersede a later state transition.
cr_latest_verdict_at_head="$(jq -r --arg sha "$head_sha" '
def effective_at:
[.submitted_at, .last_edited_at] | map(select(. != null)) | max // "";
[.[]
| select(.user.login == "coderabbitai[bot]")
| select(.commit_id == $sha)
| select(.state == "APPROVED" or .state == "CHANGES_REQUESTED"
or .state == "DISMISSED")]
| sort_by(effective_at) | last | .state // empty' "$reviews_json")"
| sort_by(.submitted_at // "") | last | .state // empty' "$reviews_json")"

cr_approved_anywhere="$(jq -r '
[.[] | select(.user.login == "coderabbitai[bot]" and .state == "APPROVED")]
Expand Down Expand Up @@ -100,11 +100,11 @@ cr_commented_probe="$(jq -r --arg sha "$head_sha" '
def effective_at:
[.submitted_at, .last_edited_at] | map(select(. != null)) | max // "";
([.[]
| select(.user.login == "coderabbitai[bot]")
| select(.commit_id == $sha)
| select(.state == "APPROVED" or .state == "CHANGES_REQUESTED"
| select(.user.login == "coderabbitai[bot]")
| select(.commit_id == $sha)
| select(.state == "APPROVED" or .state == "CHANGES_REQUESTED"
or .state == "DISMISSED")]
| sort_by(effective_at) | last | effective_at) as $verdict_at
| sort_by(.submitted_at // "") | last | (.submitted_at // "")) as $verdict_at
| [.[]
| select(.user.login == "coderabbitai[bot]")
| select(.commit_id == $sha)
Expand Down Expand Up @@ -230,18 +230,27 @@ if [[ -n "$premerge_body" ]]; then
# Header/separator rows are ignored; an unknown/pending data row is red
# even when another row passed. Requiring at least one data row keeps an
# unrecognized future shape fail-closed.
full_check_rows="$(awk '
full_check_rows="$(awk -F'|' '
/^## Pre-merge checks[[:space:]]*$/ { in_section = 1; next }
in_section && /^##[[:space:]]/ { exit }
in_section && /^\|/ {
if ($0 ~ /^\|[-[:space:]:|]+\|[[:space:]]*$/) next
if ($0 ~ /\|[[:space:]]*(Status|Result)[[:space:]]*\|/) next
status = $3
gsub(/^[[:space:]]+|[[:space:]]+$/, "", status)
if (status == "Status" || status == "Result") next
print
}
' <<<"$region")"
if [[ -n "$full_check_rows" && "$region" != *"❌"* &&
"$region" != *"❓"* && "$region" != *"⚠️"* ]] &&
! grep -qvF '✅ Passed' <<<"$full_check_rows"; then
awk -F'|' '
{
status = $3
gsub(/^[[:space:]]+|[[:space:]]+$/, "", status)
if (status != "✅ Passed") bad = 1
}
END { exit bad }
' <<<"$full_check_rows"; then
premerge_state="green"
else
premerge_state="failed"
Expand Down
Loading