feat: skip re-posting when review is unchanged (preserve threads)
CI / test (pull_request) Successful in 14s
CI / review (gpt-4.1, gpt, GPT_REVIEW_TOKEN) (pull_request) Successful in 23s
CI / review (gpt-5, security, SECURITY_REVIEW.md, SONNET_REVIEW_TOKEN) (pull_request) Successful in 1m1s
CI / review (gpt-5, sonnet, SONNET_REVIEW_TOKEN) (pull_request) Successful in 1m28s

Before posting, compare the new review body+event against the existing
review with the same sentinel. If identical, skip entirely — this
preserves conversation threads on inline comments and avoids
re-notifying reviewers for findings they already know about.

Only re-posts when findings actually change (fixed, new, or different).

Tests: 6 cases covering identical, different body, different state,
stale reviews, and different sentinels.
This commit is contained in:
Rodin
2026-05-01 22:17:36 -07:00
parent b0dc6d0c09
commit 1c2292265b
2 changed files with 108 additions and 0 deletions
+79
View File
@@ -148,3 +148,82 @@ func TestShouldEscalate(t *testing.T) {
})
}
}
func TestReviewUnchanged(t *testing.T) {
tests := []struct {
name string
existing []gitea.Review
newBody string
newEvent string
sentinel string
want bool
}{
{
name: "no existing review",
existing: nil,
newBody: "new review",
newEvent: "APPROVED",
sentinel: "<!-- review-bot:sonnet -->",
want: false,
},
{
name: "identical body and state",
existing: []gitea.Review{
makeReview(100, "bot", "APPROVED", false, "same body\n<!-- review-bot:sonnet -->"),
},
newBody: "same body\n<!-- review-bot:sonnet -->",
newEvent: "APPROVED",
sentinel: "<!-- review-bot:sonnet -->",
want: true,
},
{
name: "same body but different state",
existing: []gitea.Review{
makeReview(100, "bot", "APPROVED", false, "body\n<!-- review-bot:sonnet -->"),
},
newBody: "body\n<!-- review-bot:sonnet -->",
newEvent: "REQUEST_CHANGES",
sentinel: "<!-- review-bot:sonnet -->",
want: false,
},
{
name: "different body same state",
existing: []gitea.Review{
makeReview(100, "bot", "APPROVED", false, "old body\n<!-- review-bot:sonnet -->"),
},
newBody: "new body\n<!-- review-bot:sonnet -->",
newEvent: "APPROVED",
sentinel: "<!-- review-bot:sonnet -->",
want: false,
},
{
name: "stale review with same body (should still post)",
existing: []gitea.Review{
makeReview(100, "bot", "APPROVED", true, "same\n<!-- review-bot:sonnet -->"),
},
newBody: "same\n<!-- review-bot:sonnet -->",
newEvent: "APPROVED",
sentinel: "<!-- review-bot:sonnet -->",
want: false,
},
{
name: "different sentinel (not our review)",
existing: []gitea.Review{
makeReview(100, "bot", "APPROVED", false, "body\n<!-- review-bot:gpt -->"),
},
newBody: "body\n<!-- review-bot:sonnet -->",
newEvent: "APPROVED",
sentinel: "<!-- review-bot:sonnet -->",
want: false,
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
got := reviewUnchanged(tc.existing, tc.newBody, tc.newEvent, tc.sentinel)
if got != tc.want {
t.Errorf("reviewUnchanged() = %v, want %v", got, tc.want)
}
})
}
}