From 5bdbcb0ac6089db1411319e4990897682ad7938f Mon Sep 17 00:00:00 2001 From: Michael Fix Date: Thu, 29 Aug 2019 18:38:56 -0700 Subject: [PATCH] Update pulls (#76) * merge base branch if required * add unit test * enable for me for now --- src/api.js | 3 ++- src/pull/labeled.js | 29 +++++++++++++++++++++++- test/index.test.js | 55 ++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 84 insertions(+), 3 deletions(-) diff --git a/src/api.js b/src/api.js index d499d16..ecda8e7 100644 --- a/src/api.js +++ b/src/api.js @@ -29,7 +29,8 @@ exports.getPullRequest = function getPullRequest(github, data) { repo, pull_number: number, headers: { - Accept: 'application/vnd.github.symmetra-preview+json' + Accept: + 'application/vnd.github.symmetra-preview+json,application/vnd.github.shadow-cat-preview+json' } }) .then(_ => _.data) diff --git a/src/pull/labeled.js b/src/pull/labeled.js index 5672df2..4a43c53 100644 --- a/src/pull/labeled.js +++ b/src/pull/labeled.js @@ -111,7 +111,6 @@ module.exports.process = robot => async ({ pull = await getPullRequest(github, { owner, repo, number }) } catch (error) { const Sentry = require('@sentry/node') - robot.log('Get pull request failed', error, { installation_id, owner, repo, number, method }) Sentry.configureScope(scope => { scope.setUser({ username: owner, id: installation_id }) Sentry.captureException(error) @@ -200,6 +199,34 @@ module.exports.process = robot => async ({ await mergeAttempt(2) } } + } else if (pull.mergeable_state === STATUS.BEHIND) { + // TODO use getBranchProtection? + const { data: branch } = await github.repos.getBranch({ + owner: pull.base.user.login, + repo: pull.base.repo.name, + branch: pull.base.ref + }) + if ( + branch.protected && + branch.protection && + branch.protection.enabled && + branch.protection.required_status_checks && + branch.protection.required_status_checks.enforcement_level !== 'off' && + branch.protection.required_status_checks.contexts.length && + // TODO + (owner === 'carbon-app' || owner === 'mfix22') + ) { + await github.pulls.updateBranch({ + owner, + repo, + pull_number: number, + expected_head_sha: pull.base.sha, + headers: { + accept: 'application/vnd.github.lydian-preview+json' + } + }) + return + } } else if (pull.mergeable_state === STATUS.DIRTY) { // don't retry if there are merge conflicts return diff --git a/test/index.test.js b/test/index.test.js index 5fbd197..e247e13 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -202,7 +202,18 @@ beforeEach(async () => { }), getCombinedStatusForRef: jest .fn() - .mockResolvedValue({ data: { state: 'success', statuses: [] } }) + .mockResolvedValue({ data: { state: 'success', statuses: [] } }), + getBranch: jest.fn().mockResolvedValue({ + data: { + protected: true, + protection: { + enabled: true, + required_status_checks: { + contexts: ['Build'] + } + } + } + }) }, apps: { listRepos: jest.fn().mockResolvedValue({ @@ -224,6 +235,9 @@ beforeEach(async () => { }, users: { getByUsername: jest.fn().mockResolvedValue({ data: { email: 'test@test.com' } }) + }, + pulls: { + updateBranch: jest.fn().mockResolvedValue({ data: {} }) } } robot.auth = () => Promise.resolve(github) @@ -379,6 +393,45 @@ describe('pull_request', () => { }) }) + test('Will not update branch if a pull request is "behind" and branch requires it', async () => { + github.pullRequests.get.mockResolvedValue({ + data: { + mergeable: true, + mergeable_state: 'behind', + base: { + sha: 'fake sha ahhh', + user: { login: 'mfix22' }, + repo: { name: 'test-issue-bot', owner: { login: 'mfix22' } } + }, + head: { + sha: 0, + user: { login: 'mfix22' }, + repo: { name: 'test-issue-bot', owner: { login: 'mfix22' } } + } + } + }) + + await robot.receive( + payload({ + name: 'pull_request', + threadType: 'pull_request', + labels: ['merge'], + number: 98 + }) + ) + + await wait(10) + + expect(github.pullRequests.merge).not.toHaveBeenCalled() + expect(github.pulls.updateBranch).toHaveBeenCalledWith({ + expected_head_sha: 'fake sha ahhh', + owner: 'mfix22', + pull_number: 98, + repo: 'test-issue-bot', + headers: { accept: 'application/vnd.github.lydian-preview+json' } + }) + }) + test('Will not merge a pull request with state `dirty`', async () => { github.pullRequests.get.mockResolvedValue({ data: {