Disable auto-merge for unstable GitHub PRs (#7415)

Prevent enabling auto-merge when a PR is in an UNSTABLE merge state.
GitHub auto-merge mutations reject UNSTABLE PRs directly instead of
allowing them to wait, so we should suppress the option.
This commit is contained in:
Jinjing
2026-07-05 11:05:58 -07:00
committed by GitHub
parent 492bbe31b6
commit e7d1fa4a21
4 changed files with 33 additions and 3 deletions
@@ -15,6 +15,10 @@ function isConflicting(item: MobilePRAutoMergeAvailabilityInput): boolean {
return item.mergeable === 'CONFLICTING' || item.mergeStateStatus === 'DIRTY'
}
function isUnstable(item: MobilePRAutoMergeAvailabilityInput): boolean {
return item.mergeStateStatus === 'UNSTABLE'
}
function hasReviewRequirement(item: MobilePRAutoMergeAvailabilityInput): boolean {
return item.reviewDecision === 'REVIEW_REQUIRED' || item.reviewDecision === 'CHANGES_REQUESTED'
}
@@ -27,7 +31,9 @@ function canMergeImmediately(item: MobilePRAutoMergeAvailabilityInput): boolean
}
function canRequestWhenReady(item: MobilePRAutoMergeAvailabilityInput): boolean {
if (item.state !== 'open' || isConflicting(item)) {
// Why: GitHub auto-merge waits on unmet requirements; UNSTABLE is rejected
// by the mutation rather than becoming a waitable auto-merge request.
if (item.state !== 'open' || isConflicting(item) || isUnstable(item)) {
return false
}
if (item.mergeQueueRequired === true) {
@@ -62,6 +62,18 @@ describe('presentGitHubPRMergeState', () => {
})
})
it('does not offer enable auto-merge for GitHub unstable PRs', () => {
expect(
presentGitHubPRMergeState(
pr({
mergeable: 'UNKNOWN',
mergeStateStatus: 'UNSTABLE',
checksSummary: { state: 'failure', total: 1, passed: 0, failed: 1, pending: 0 }
})
).autoMergeAction
).toBeNull()
})
it('does not offer enable auto-merge on conflicting PRs (GitHub would reject it)', () => {
expect(
presentGitHubPRMergeState(pr({ mergeable: 'CONFLICTING', mergeStateStatus: 'DIRTY' }))
@@ -48,7 +48,7 @@ describe('github PR auto-merge availability', () => {
expect(canShowGitHubPRAutoMergeControl(pr({ autoMergeEnabled: true }))).toBe(true)
})
it('suppresses closed, draft, disallowed, and conflicting PRs', () => {
it('suppresses closed, draft, disallowed, conflicting, and unstable PRs', () => {
expect(
canShowGitHubPRAutoMergeControl(pr({ state: 'draft', mergeStateStatus: 'BLOCKED' }))
).toBe(false)
@@ -63,5 +63,11 @@ describe('github PR auto-merge availability', () => {
expect(
canShowGitHubPRAutoMergeControl(pr({ mergeable: 'CONFLICTING', mergeStateStatus: 'DIRTY' }))
).toBe(false)
expect(
canEnableGitHubPRAutoMerge(pr({ mergeable: 'UNKNOWN', mergeStateStatus: 'UNSTABLE' }))
).toBe(false)
expect(
canShowGitHubPRAutoMergeControl(pr({ mergeable: 'UNKNOWN', mergeStateStatus: 'UNSTABLE' }))
).toBe(false)
})
})
@@ -18,6 +18,10 @@ function isConflicting(item: GitHubPRAutoMergeAvailabilityInput): boolean {
return item.mergeable === 'CONFLICTING' || item.mergeStateStatus === 'DIRTY'
}
function isUnstable(item: GitHubPRAutoMergeAvailabilityInput): boolean {
return item.mergeStateStatus === 'UNSTABLE'
}
function hasReviewRequirement(item: GitHubPRAutoMergeAvailabilityInput): boolean {
return item.reviewDecision === 'REVIEW_REQUIRED' || item.reviewDecision === 'CHANGES_REQUESTED'
}
@@ -30,7 +34,9 @@ function canMergeImmediately(item: GitHubPRAutoMergeAvailabilityInput): boolean
}
function canRequestWhenReady(item: GitHubPRAutoMergeAvailabilityInput): boolean {
if (!isOpenPR(item) || isConflicting(item)) {
// Why: GitHub auto-merge waits on unmet requirements; UNSTABLE is rejected
// by the mutation rather than becoming a waitable auto-merge request.
if (!isOpenPR(item) || isConflicting(item) || isUnstable(item)) {
return false
}
if (item.mergeQueueRequired === true) {