Skip to content

fix(code-review): preserve in-flight review on merge commit push#2741

Merged
alex-alecu merged 7 commits intomainfrom
fix/preserve-review-on-merge-commit
Apr 28, 2026
Merged

fix(code-review): preserve in-flight review on merge commit push#2741
alex-alecu merged 7 commits intomainfrom
fix/preserve-review-on-merge-commit

Conversation

@alex-alecu
Copy link
Copy Markdown
Contributor

Why

When someone clicked GitHub's "Update branch" button (or merged main into their feature branch), the code review that was already running on their pull request would disappear. It would get cancelled, and no new review would take its place, leaving the PR with nothing. This made it look like our bot just forgot about the PR.

What changed

The webhook that handles new commits on a pull request now checks whether the new commit is a merge commit before it decides to cancel the running review. If it is a merge commit, the webhook quietly walks away and lets the existing review keep running on the real feature commit, where it is useful. Previously the order was reversed — cancel first, then notice it was a merge commit — which threw the valid review away for no reason. The same fix is applied on the GitLab side for merge requests. Small helper functions were extracted so the decision logic is easy to unit test.

How to test

  1. Open a pull request and push a real feature commit. Wait for a code review to start running.
  2. While the review is still running, click "Update branch" on the PR so GitHub creates a merge commit on your branch.
  3. Open the review row in the database (or the Kilo dashboard) and confirm the review's status has not changed to "cancelled" — it should still be running or completed against the earlier feature commit.
  4. Wait for the review to finish and confirm it posted its summary comment on the PR as normal.
  5. Push another feature commit and confirm a fresh review starts for that new commit.

Visual Changes

N/A

Reviewer Notes

The behaviour only changes in one scenario: a synchronize/update webhook whose head is a merge commit and there is already an in-flight review. All other paths (normal pushes, no prior review, opened/reopened events) are unchanged. The merge-commit detection itself was already in the codebase; this PR only moves it earlier in the handler. Downstream logic that picks the incremental review baseline (findPreviousCompletedReview) already filters on status = 'completed' and benefits automatically from not losing the prior review.

When a pull_request.synchronize / merge_request.update event arrives with a merge-commit head (e.g. clicking GitHub's 'Update branch' button), the review was being cancelled before the merge-commit skip check ran, leaving the PR with no active review. Reorder so the merge-commit check runs first and bails out without touching existing reviews. Extract the decision into small pure helpers for unit testing.
@kilo-code-bot
Copy link
Copy Markdown
Contributor

kilo-code-bot Bot commented Apr 23, 2026

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Files Reviewed (1 files)
  • apps/web/src/lib/integrations/platforms/github/webhook-handlers/pull-request-handler.ts

Reviewed by gpt-5.4-20260305 · 670,437 tokens

@alex-alecu
Copy link
Copy Markdown
Contributor Author

Local testing

All three scenarios pass against the branch currently checked out.

Setup

  • PR branch fix/preserve-review-on-merge-commit already checked out, HEAD at 27f94ce4a
  • Homebrew postgresql@17 running on :5432
  • Services started via ./dev/review/dev-review.sh — root/Next.js (:3000), review worker (:8789), session worker (:8800). agent-next failed to start (Docker not running, not needed for this test)
  • Seeded kilocode_users, platform_integrations (installation 112613665 → user-owned), agent_configs (code_review/github enabled) to let the webhook handler reach the decision logic
  • Set services/code-review-infra/.dev.vars with CLOUD_AGENT_NEXT_URL=http://127.0.0.1:18794 (dead port) to avoid accidentally hitting production cloud-agent-next
  • Used the user-provided payload as the base; three variants written to dev/.dev-logs/review-test/:
    • happy-regular.json head.sha=e0961cf65f... (1 parent)
    • merge-commit.json head.sha=243305a151... (2 parents — real merge commit from the original PR)
    • supersede-regular.json head.sha=35aca4520f... (1 parent)

Scenario A — Happy flow (regular commit)

  • POST /api/webhooks/github202 "Code review queued" (reviewId 02afd169-…)
  • [isMergeCommit]parentCount: 1, isMergeCommit: false ← real GitHub API call succeeded
  • Logs observed: Pull request event receivedCode review agent enabledCreated code reviewCreated check run 72918679226Added eyes reactionDispatch attempt
  • Review row persisted. Final status failed as expected (dispatch endpoint is a dead port — we only care that the decision reached "dispatch")

Scenario B — Merge commit preserves running review (the PR fix)

Pre-seeded R1 (11111111-…) with head_sha=e0961cf65..., status='running'. Sent merge-commit.json (synchronize to merge SHA 243305a1…).

  • POST /api/webhooks/github200 "Skipped merge commit"
  • [isMergeCommit]parentCount: 2, isMergeCommit: true
  • Skipping merge commit: { pr_number: 30, head_sha: '243305a1…' }
  • Migrated review 11111111-… to merge-commit head 243305a1… (check run 72918768664)
  • R1 after: status='running' (preserved), head_sha=243305a1… (migrated)
  • Cancelling N old review(s): not logged — cancel code path not executed
  • Worker POST /reviews/:id/cancel calls received: 0 ← the running review was NOT stopped ✓

Scenario C — Supersede (regular commit cancels running review)

Pre-seeded R1 (22222222-…) at e0961cf65..., status='running'. Sent supersede-regular.json (synchronize to 35aca4520…).

  • POST /api/webhooks/github202 "Code review queued" (reviewId R2 3515b0a3-…)
  • [isMergeCommit]parentCount: 1, isMergeCommit: false
  • Cancelling 1 old review(s) for alex-alecu/stories-canvas#30
  • Worker log: [POST /reviews/:reviewId/cancel] Cancelling review + POST /reviews/22222222-…/cancel 200 OK1 cancel call sent to code-review-infra
  • R2 inserted at 35aca4520…; R1 remained in DB (cancel propagation requires a live DO, not applicable for manually seeded review)

Summary

Scenario A Scenario B (merge) Scenario C (supersede)
HTTP response 202 queued 200 Skipped merge commit 202 queued
isMergeCommit result false (1 parent) true (2 parents) false (1 parent)
"Skipping merge commit" logged no yes no
"Cancelling N old review(s)" logged no (no prior R) no ← key yes (1)
Worker cancel POSTs received 0 0 ← key 1
Prior review preserved yes (running, migrated SHA) cancelled-request sent

PR #2741's merge-commit-before-cancel reorder is working end-to-end against real webhook payloads and the local stack. ✅

…n-merge-commit

# Conflicts:
#	apps/web/src/lib/integrations/platforms/github/webhook-handlers/pull-request-handler.ts
#	apps/web/src/lib/integrations/platforms/gitlab/webhook-handlers/merge-request-handler.ts
@alex-alecu alex-alecu enabled auto-merge (squash) April 27, 2026 14:39
@alex-alecu alex-alecu merged commit 2fba9db into main Apr 28, 2026
15 checks passed
@alex-alecu alex-alecu deleted the fix/preserve-review-on-merge-commit branch April 28, 2026 07:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants