From d19a4ba7095f51ee458ecb39b5d460e6e6835357 Mon Sep 17 00:00:00 2001 From: Rhys Arkins <rhys@arkins.net> Date: Tue, 16 Oct 2018 12:43:27 +0200 Subject: [PATCH] feat(github): support check-runs for branch status (#2659) Closes #2571, Closes #2616 --- lib/platform/github/index.js | 49 ++++++++++++-- test/platform/github/index.spec.js | 102 ++++++++++++++++++++++++++++- 2 files changed, 145 insertions(+), 6 deletions(-) diff --git a/lib/platform/github/index.js b/lib/platform/github/index.js index 186ed7b3f8..efd522dfec 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 e34982a299..346596dacb 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 () => { -- GitLab