Merge "Merge pull requests from github reporter" into feature/zuulv3

This commit is contained in:
Jenkins
2017-05-16 22:01:49 +00:00
committed by Gerrit Code Review
7 changed files with 106 additions and 2 deletions

View File

@@ -50,6 +50,11 @@ reporter. It has the following options:
to ``true``.
``comment: false``
**merge**
Boolean value (``true`` or ``false``) that determines if the reporter should
merge the pull reqeust. Defaults to ``false``.
``merge=true``
SMTP
----

View File

@@ -1,6 +1,6 @@
pbr>=1.1.0
Github3.py
Github3.py==1.0.0a2
PyYAML>=3.1.0
Paste
WebOb>=1.2.3

View File

@@ -70,6 +70,7 @@ import zuul.merger.merger
import zuul.merger.server
import zuul.nodepool
import zuul.zk
from zuul.exceptions import MergeFailure
FIXTURE_DIR = os.path.join(os.path.dirname(__file__),
'fixtures')
@@ -559,6 +560,7 @@ class FakeGithubPullRequest(object):
self.statuses = {}
self.updated_at = None
self.head_sha = None
self.is_merged = False
self._createPRRef()
self._addCommitToRepo()
self._updateTimeStamp()
@@ -693,6 +695,8 @@ class FakeGithubConnection(githubconnection.GithubConnection):
self.pr_number = 0
self.pull_requests = []
self.upstream_root = upstream_root
self.merge_failure = False
self.merge_not_allowed_count = 0
def openFakePullRequest(self, project, branch):
self.pr_number += 1
@@ -762,6 +766,16 @@ class FakeGithubConnection(githubconnection.GithubConnection):
pull_request = self.pull_requests[pr_number - 1]
pull_request.addComment(message)
def mergePull(self, project, pr_number, sha=None):
pull_request = self.pull_requests[pr_number - 1]
if self.merge_failure:
raise Exception('Pull request was not merged')
if self.merge_not_allowed_count > 0:
self.merge_not_allowed_count -= 1
raise MergeFailure('Merge was not successful due to mergeability'
' conflict')
pull_request.is_merged = True
def setCommitStatus(self, project, sha, state,
url='', description='', context=''):
owner, proj = project.split('/')

View File

@@ -0,0 +1,19 @@
- pipeline:
name: merge
description: Pipeline for merging the pull request
manager: independent
trigger:
github:
- event: pull_request
action: comment
comment: 'merge me'
success:
github:
merge: true
comment: false
- project:
name: org/project
merge:
jobs:
- noop

View File

@@ -165,3 +165,35 @@ class TestGithubDriver(ZuulTestCase):
self.waitUntilSettled()
self.assertNotIn('reporting', pr.statuses)
self.assertEqual(2, len(pr.comments))
@simple_layout('layouts/merging-github.yaml', driver='github')
def test_report_pull_merge(self):
# pipeline merges the pull request on success
A = self.fake_github.openFakePullRequest('org/project', 'master')
self.fake_github.emitEvent(A.getCommentAddedEvent('merge me'))
self.waitUntilSettled()
self.assertTrue(A.is_merged)
# pipeline merges the pull request on success after failure
self.fake_github.merge_failure = True
B = self.fake_github.openFakePullRequest('org/project', 'master')
self.fake_github.emitEvent(B.getCommentAddedEvent('merge me'))
self.waitUntilSettled()
self.assertFalse(B.is_merged)
self.fake_github.merge_failure = False
# pipeline merges the pull request on second run of merge
# first merge failed on 405 Method Not Allowed error
self.fake_github.merge_not_allowed_count = 1
C = self.fake_github.openFakePullRequest('org/project', 'master')
self.fake_github.emitEvent(C.getCommentAddedEvent('merge me'))
self.waitUntilSettled()
self.assertTrue(C.is_merged)
# pipeline does not merge the pull request
# merge failed on 405 Method Not Allowed error - twice
self.fake_github.merge_not_allowed_count = 2
D = self.fake_github.openFakePullRequest('org/project', 'master')
self.fake_github.emitEvent(D.getCommentAddedEvent('merge me'))
self.waitUntilSettled()
self.assertFalse(D.is_merged)

View File

@@ -21,9 +21,11 @@ import webob
import webob.dec
import voluptuous as v
import github3
from github3.exceptions import MethodNotAllowed
from zuul.connection import BaseConnection
from zuul.model import PullRequest, Ref, TriggerEvent
from zuul.exceptions import MergeFailure
class GithubWebhookListener():
@@ -283,6 +285,17 @@ class GithubConnection(BaseConnection):
pull_request = repository.issue(pr_number)
pull_request.create_comment(message)
def mergePull(self, project, pr_number, sha=None):
owner, proj = project.split('/')
pull_request = self.github.pull_request(owner, proj, pr_number)
try:
result = pull_request.merge(sha=sha)
except MethodNotAllowed as e:
raise MergeFailure('Merge was not successful due to mergeability'
' conflict, original error is %s' % e)
if not result:
raise Exception('Pull request was not merged')
def setCommitStatus(self, project, sha, state, url='', description='',
context=''):
owner, proj = project.split('/')

View File

@@ -14,8 +14,10 @@
import logging
import voluptuous as v
import time
from zuul.reporter import BaseReporter
from zuul.exceptions import MergeFailure
class GithubReporter(BaseReporter):
@@ -28,6 +30,7 @@ class GithubReporter(BaseReporter):
super(GithubReporter, self).__init__(driver, connection, config)
self._commit_status = self.config.get('status', None)
self._create_comment = self.config.get('comment', True)
self._merge = self.config.get('merge', False)
def report(self, source, pipeline, item):
"""Comment on PR and set commit status."""
@@ -37,6 +40,9 @@ class GithubReporter(BaseReporter):
hasattr(item.change, 'patchset') and
item.change.patchset is not None):
self.setPullStatus(pipeline, item)
if (self._merge and
hasattr(item.change, 'number')):
self.mergePull(item)
def addPullComment(self, pipeline, item):
message = self._formatItemReport(pipeline, item)
@@ -68,10 +74,25 @@ class GithubReporter(BaseReporter):
self.connection.setCommitStatus(
project, sha, state, url, description, context)
def mergePull(self, item):
project = item.change.project.name
pr_number = item.change.number
sha = item.change.patchset
self.log.debug('Reporting change %s, params %s, merging via API' %
(item.change, self.config))
try:
self.connection.mergePull(project, pr_number, sha)
except MergeFailure:
time.sleep(2)
self.log.debug('Trying to merge change %s again...' % item.change)
self.connection.mergePull(project, pr_number, sha)
item.change.is_merged = True
def getSchema():
github_reporter = v.Schema({
'status': v.Any('pending', 'success', 'failure'),
'comment': bool
'comment': bool,
'merge': bool
})
return github_reporter