diff --git a/lib/platform/github/index.js b/lib/platform/github/index.js index 186ed7b3f85633b0c48d57703a92e75eb9289e91..efd522dfec551db067270a25476e7eb1a5357996 100644 --- a/lib/platform/github/index.js +++ b/lib/platform/github/index.js @@ -494,13 +494,54 @@ async function getBranchStatus(branchName, requiredStatusChecks) { logger.warn({ requiredStatusChecks }, `Unsupported requiredStatusChecks`); return 'failed'; } - const gotString = `repos/${config.repository}/commits/${branchName}/status`; - const res = await get(gotString); + const commitStatusUrl = `repos/${ + config.repository + }/commits/${branchName}/status`; + const commitStatus = (await get(commitStatusUrl)).body; logger.debug( - { state: res.body.state, statuses: res.body.statuses }, + { state: commitStatus.state, statuses: commitStatus.statuses }, 'branch status check result' ); - return res.body.state; + let checkRuns = []; + if (!config.isGhe) { + try { + const checkRunsUrl = `repos/${ + config.repository + }/commits/${branchName}/check-runs`; + const opts = { + headers: { + Accept: 'application/vnd.github.antiope-preview+json', + }, + }; + const checkRunsRaw = (await get(checkRunsUrl, opts)).body; + if (checkRunsRaw.check_runs && checkRunsRaw.check_runs.length) { + checkRuns = checkRunsRaw.check_runs.map(run => ({ + name: run.name, + status: run.status, + conclusion: run.conclusion, + })); + logger.debug({ checkRuns }, 'check runs result'); + } + } catch (err) { + logger.warn({ err }, 'Error retrieving check runs'); + } + } + if (checkRuns.length === 0) { + return commitStatus.state; + } + if ( + commitStatus.state === 'failed' || + checkRuns.some(run => run.conclusion === 'failed') + ) { + return 'failed'; + } + if ( + (commitStatus.state === 'success' || commitStatus.statuses.length === 0) && + checkRuns.every(run => run.conclusion === 'success') + ) { + return 'success'; + } + return 'pending'; } async function getBranchStatusCheck(branchName, context) { diff --git a/test/platform/github/index.spec.js b/test/platform/github/index.spec.js index e34982a299789ee956b7f2bc117d660af492dbb2..346596dacbf8a8b7ec6a53b98b548dd6c289ac29 100644 --- a/test/platform/github/index.spec.js +++ b/test/platform/github/index.spec.js @@ -584,8 +584,8 @@ describe('platform/github', () => { expect(pr).toMatchSnapshot(); }); }); - describe('getBranchStatus(branchName, requiredStatusChecks)', () => { - it('returne success if requiredStatusChecks null', async () => { + describe('getBranchStatus()', () => { + it('returns success if requiredStatusChecks null', async () => { await initRepo({ repository: 'some/repo', token: 'token', @@ -627,6 +627,104 @@ describe('platform/github', () => { const res = await github.getBranchStatus('somebranch', []); expect(res).toEqual('failed'); }); + it('should fail if a check run has failed', async () => { + await initRepo({ + repository: 'some/repo', + token: 'token', + }); + get.mockImplementationOnce(() => ({ + body: { + state: 'pending', + statuses: [], + }, + })); + get.mockImplementationOnce(() => ({ + body: { + total_count: 2, + check_runs: [ + { + id: 23950198, + status: 'completed', + conclusion: 'success', + name: 'Travis CI - Pull Request', + }, + { + id: 23950195, + status: 'completed', + conclusion: 'failed', + name: 'Travis CI - Branch', + }, + ], + }, + })); + const res = await github.getBranchStatus('somebranch', []); + expect(res).toEqual('failed'); + }); + it('should suceed if no status and all passed check runs', async () => { + await initRepo({ + repository: 'some/repo', + token: 'token', + }); + get.mockImplementationOnce(() => ({ + body: { + state: 'pending', + statuses: [], + }, + })); + get.mockImplementationOnce(() => ({ + body: { + total_count: 2, + check_runs: [ + { + id: 23950198, + status: 'completed', + conclusion: 'success', + name: 'Travis CI - Pull Request', + }, + { + id: 23950195, + status: 'completed', + conclusion: 'success', + name: 'Travis CI - Branch', + }, + ], + }, + })); + const res = await github.getBranchStatus('somebranch', []); + expect(res).toEqual('success'); + }); + it('should fail if a check run has failed', async () => { + await initRepo({ + repository: 'some/repo', + token: 'token', + }); + get.mockImplementationOnce(() => ({ + body: { + state: 'pending', + statuses: [], + }, + })); + get.mockImplementationOnce(() => ({ + body: { + total_count: 2, + check_runs: [ + { + id: 23950198, + status: 'completed', + conclusion: 'success', + name: 'Travis CI - Pull Request', + }, + { + id: 23950195, + status: 'pending', + name: 'Travis CI - Branch', + }, + ], + }, + })); + const res = await github.getBranchStatus('somebranch', []); + expect(res).toEqual('pending'); + }); }); describe('getBranchStatusCheck', () => { it('returns state if found', async () => {