diff --git a/lib/modules/platform/github/index.spec.ts b/lib/modules/platform/github/index.spec.ts index c9dd817f40ee39..d7b64aae913c55 100644 --- a/lib/modules/platform/github/index.spec.ts +++ b/lib/modules/platform/github/index.spec.ts @@ -2815,6 +2815,27 @@ describe('modules/platform/github/index', () => { }) ).toBeFalse(); }); + + it('should handle merge block', async () => { + const scope = httpMock.scope(githubApiHost); + initRepoMock(scope, 'some/repo'); + scope + .put('/repos/some/repo/pulls/1234/merge') + .reply(405, { message: 'Required status check "build" is expected.' }); + await github.initRepo({ repository: 'some/repo' }); + const pr = { + number: 1234, + head: { + ref: 'someref', + }, + }; + expect( + await github.mergePr({ + branchName: '', + id: pr.number, + }) + ).toBeFalse(); + }); }); describe('massageMarkdown(input)', () => { diff --git a/lib/modules/platform/github/index.ts b/lib/modules/platform/github/index.ts index caf65f1acb4c16..d6e9df4d2bd335 100644 --- a/lib/modules/platform/github/index.ts +++ b/lib/modules/platform/github/index.ts @@ -32,6 +32,8 @@ import type { } from '../../../util/git/types'; import * as hostRules from '../../../util/host-rules'; import * as githubHttp from '../../../util/http/github'; +import type { GithubHttpOptions } from '../../../util/http/github'; +import type { HttpResponse } from '../../../util/http/types'; import { regEx } from '../../../util/regex'; import { sanitize } from '../../../util/sanitize'; import { fromBase64, looseEquals } from '../../../util/string'; @@ -1605,15 +1607,15 @@ export async function mergePr({ const url = `repos/${ config.parentRepo ?? config.repository }/pulls/${prNo}/merge`; - const options: any = { - body: {} as { merge_method?: string }, + const options: GithubHttpOptions = { + body: {}, }; // istanbul ignore if if (config.forkToken) { options.token = config.forkToken; } let automerged = false; - let automergeResult: any; + let automergeResult: HttpResponse; if (config.mergeMethod) { // This path is taken if we have auto-detected the allowed merge types from the repo options.body.merge_method = config.mergeMethod; @@ -1623,9 +1625,19 @@ export async function mergePr({ automerged = true; } catch (err) { if (err.statusCode === 404 || err.statusCode === 405) { - // istanbul ignore next + const body = err.response?.body; + if ( + is.nonEmptyString(body?.message) && + regEx(/^Required status check ".+" is expected\.$/).test(body.message) + ) { + logger.debug( + { response: body }, + `GitHub blocking PR merge -- Missing required status check(s)` + ); + return false; + } logger.debug( - { response: err.response ? err.response.body : undefined }, + { response: body }, 'GitHub blocking PR merge -- will keep trying' ); } else { @@ -1661,7 +1673,7 @@ export async function mergePr({ } } logger.debug( - { automergeResult: automergeResult.body, pr: prNo }, + { automergeResult: automergeResult!.body, pr: prNo }, 'PR merged' ); const cachedPr = config.prList?.find(({ number }) => number === prNo);