fix(scm-github): avoid conflict misclassification for draft/blocking states#1357
fix(scm-github): avoid conflict misclassification for draft/blocking states#1357ChiragArora31 wants to merge 5 commits into
Conversation
ReviewOverviewTwo-line behavior fix in Correctness — looks right
Test coverage — one gap
Style / minor
Risks
VerdictApprove with a small request: add one draft-PR regression test ( |
|
@harsh-batheja, I have fixed the issues; please review |
Compute noConflicts from explicit CONFLICTING mergeability only so draft/blocked/unknown states do not trigger merge-conflict reactions. Made-with: Cursor
… and document noConflicts - Clarify that noConflicts follows graphql-batch semantics (not conflicting unless mergeable is CONFLICTING). - Add draft PR with MERGEABLE + BLOCKED merge state asserting noConflicts true while draft/branch-protection blockers keep mergeable false. Made-with: Cursor
74e22fb to
b1121a4
Compare
…ct-classification
Greptile SummaryThis PR fixes a bug where GitHub's
Confidence Score: 5/5Safe to merge — the change is a minimal, targeted one-line fix with correct semantics and full test coverage for the regression scenario. The fix correctly narrows the conflict signal to CONFLICTING only, preserving all other blockers through the existing blockers array. The regression test (draft + UNKNOWN + BLOCKED) now exercises exactly the scenario described in the bug report and would have failed against the old code. No other logic paths are touched. No files require special attention.
|
| Filename | Overview |
|---|---|
| packages/plugins/scm-github/src/index.ts | Single-line logic fix: noConflicts now derives from mergeable !== "CONFLICTING" instead of mergeable === "MERGEABLE", correctly isolating conflict detection from draft/BLOCKED/UNKNOWN GitHub states. |
| packages/plugins/scm-github/test/index.test.ts | Test updates flip the UNKNOWN assertion from false→true, rename the test to reflect new semantics, add a noConflicts assertion to the review-required case, and add a proper regression test for draft+UNKNOWN+BLOCKED that would have failed under old logic. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[getMergeability called] --> B[Fetch PR data from GitHub]
B --> C{mergeable value}
C -->|CONFLICTING| D["blockers: 'Merge conflicts'\nnoConflicts = false"]
C -->|UNKNOWN or empty| E["blockers: 'Merge status unknown'\nnoConflicts = true ✅"]
C -->|MERGEABLE| F[noConflicts = true]
D --> G{mergeStateStatus}
E --> G
F --> G
G -->|BLOCKED| H["blockers: 'Merge is blocked by branch protection'"]
G -->|BEHIND| I["blockers: 'Branch is behind base branch'"]
G -->|UNSTABLE| J["blockers: 'Required checks are failing'"]
G -->|other| K[no additional blocker]
H --> L{isDraft?}
I --> L
J --> L
K --> L
L -->|true| M["blockers: 'PR is still a draft'"]
L -->|false| N[return result]
M --> N
N --> O{blockers.length === 0?}
O -->|yes| P[mergeable: true]
O -->|no| Q[mergeable: false]
style E fill:#d4edda,stroke:#28a745
style D fill:#f8d7da,stroke:#dc3545
Reviews (2): Last reviewed commit: "test(scm-github): cover unknown draft me..." | Re-trigger Greptile
Co-authored-by: Cursor <cursoragent@cursor.com>
Summary
noConflictsfrom explicitmergeable === CONFLICTINGonlyBLOCKEDandUNKNOWNmergeability outcomesRoot cause
getMergeability()setnoConflictsto true only forMERGEABLE. For draft or branch-protection-blocked PRs, GitHub can return non-MERGEABLEvalues without actual conflicts, which caused conflict-based reactions to trigger via!noConflicts.What changed
CONFLICTINGas a conflict signalBLOCKED/UNKNOWNstatesWhy this approach
It matches GitHub semantics more closely and keeps conflict reactions tied to explicit conflict data, while preserving existing blockers for review/branch-protection/draft conditions.
Testing
pnpm --filter @aoagents/ao-plugin-scm-github test -- test/index.test.tspnpm --filter @aoagents/ao-core test -- src/__tests__/lifecycle-manager.test.ts --testNamePattern "merge conflict"Closes #1314.