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
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:
@@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user