fix(lifecycle): re-arm merge-conflict nudge when a clean PR is policy-blocked - #6138
ApexYash11 wants to merge 2 commits into
Conversation
🏆 Review leaderboardSep 25, 2026–Oct 2, 2026 · UTC
Ranked by distinct external PRs reviewed, then review rounds, then PR comments. Self-activity and bot activity are excluded. Show 9 more reviewers
|
a68f2e8 to
0554a25
Compare
|
Multi-lens review (autonomous, 10 lenses), verified against the source before posting. High1. The #6104 re-arm stays broken for GitLab — the motivating "rebased clean, awaiting review" scenario never sets
|
…-blocked A PR that was conflicting, then rebased clean but left blocked pending a required review (GitHub mergeable=MERGEABLE + mergeStateStatus=BLOCKED), kept its durable conflicting dedup signature, so the next real conflict was swallowed as a duplicate. The Blocked enum cannot prove a conflict is gone, so the providers now carry the positive MERGEABLE rollup out of band in SCMMergeabilityObservation.ConflictsCleared, the projection copies it to PRObservation, and the re-arm gate ORs it in. Fixes OrchestratorInc#6104.
f97705c to
c49a30a
Compare
c49a30a to
f8918e9
Compare
|
Thanks for the thorough review — all three points are addressed in 1. The fact is now computed once above the switch by a new
The motivating post-rebase path ( 2. out.ConflictsCleared = mergeable == "MERGEABLE" || mergeable == "CAN_BE_MERGED" || state == "MERGEABLE"The GitHub live path ( 3. Test gaps closed:
Verification: |
Fixes #6104
TL;DR
A worker was never told about a returning merge conflict when its PR went
conflicting -> rebased clean but still blocked (for example, waiting on a
required review) -> conflicting again. The
blockedstate alone cannot provethe conflict went away, so the dedup never re-armed. Providers now report the
positive "no conflicts" signal out of band (
ConflictsCleared), and thelifecycle re-arm gate honors it.
What was happening
durable "conflicting" signature in
pr.last_nudge_signature).mergeable=MERGEABLEwithmergeStateStatus=BLOCKED; GitLab typicallylands on
detailed_merge_status=not_approved(rebase reset approvals) orci_still_running(pipeline re-running).blocked, notmergeable, the re-arm gate stayedshut and the old "conflicting" signature survived — across restarts too.
swallowed as a duplicate. The worker stayed silent while the sidebar showed
"Merge Conflicts".
The fix
The provider's own merge rollup already knows conflicts are gone, so it now
travels out of band alongside the derived state:
backend/internal/ports/scm_observations.go— newConflictsClearedflagon
SCMMergeabilityObservation(plus a mirror onPRObservation).backend/internal/adapters/scm/github/observer_provider.go— set from theMERGEABLErollup, even when policy/CI/draft/review forcesblocked.backend/internal/adapters/scm/gitlab/observer_provider.go— set fromevery computed non-conflict
detailed_merge_status(see table below), evenwhen the MR is blocked for an unrelated reason. New
gitlabMergeStatusRulesOutConflictshelper computes it once above theswitch and threads it into every return.
backend/internal/observe/scm/observer.go— local recompute(
mergeabilityFromProviderFacts) is now provider-neutral(
MERGEABLE/CAN_BE_MERGED/ merge-statemergeable), and thepersisted-state override carries the flag so a review-only refresh cannot
drop it.
backend/internal/lifecycle/reactions.go— the re-arm gate ORs the flag in.Which GitLab statuses set the flag
true— GitLab computed the merge, no conflictmergeable,can_be_merged,ci_must_pass,ci_still_running,discussions_not_resolved,draft_status,requested_changes,not_approved, and the provider-blocked set (not_open,locked_paths, ...)false— not proof the conflict is goneconflict/cannot_be_merged*, not-yet-computed (checking,preparing,unchecked,approvals_syncing,""), unknown future statuses, andneed_rebase(documented boundary: behind-base alone does not prove conflict-free)Review feedback addressed
The review noted the first version only fixed GitHub:
mergeabilityFromMRset the flag solely on the unblocked
mergeablereturn (which adds nothing —MergeMergeablealready re-armed), and the local recompute only recognizedGitHub's
MERGEABLEenum while GitLab persistscan_be_merged/mergeable. This update:mergeabilityFromMRreturn via the newhelper, so
not_approved/ci_still_runningafter a rebase re-arm.mergeabilityFromProviderFacts(and the GitHub live path forconsistency) provider-neutral, so the live and replay paths agree.
ci_still_running/not_approved(+ the full blocked set, unknown-statusboundary) in the GitLab provider test, and a GitLab-shaped wiring leg
matching real
mergeabilityFromMRoutput.Verification
Focused suites pass:
go vetis clean on the touched packages. Broader regression coverage for there-arm lives at every layer: provider mapping (GitHub + GitLab), local
projection + persisted-state override (
internal/observe/scm), re-arm gate(
internal/lifecycle), and end-to-end over the real sqlite store includingrestart replay (
internal/daemon).