Allow to select the merge method in Github
Instead of creating a merge commit, Github also allows for two other options, squash and rebase. This change makes the github reporter aware of the merge-mode which already can be set. For now only merge and merge-resolve are supported which both map to the Github merge mode 'merge'. The other two merge modes that are supported by Github are not yet supported by the merger and will be implemented in later changes. Change-Id: I3d51261f248072d2e3ee7e3212377f81b9a41010 Co-Authored-By: Tobias Henkel <tobias.henkel@bmw.de>
This commit is contained in:
parent
48c049db79
commit
3f485be486
|
@ -1342,7 +1342,8 @@ pipeline.
|
|||
|
||||
The merge mode which is used by Git for this project. Be sure
|
||||
this matches what the remote system which performs merges (i.e.,
|
||||
Gerrit or GitHub).
|
||||
Gerrit). The requested merge mode will be used by the Github driver
|
||||
when performing merges.
|
||||
|
||||
Each project may only have one ``merge-mode`` therefore Zuul
|
||||
will use the first value that it encounters for a given project
|
||||
|
@ -1353,18 +1354,20 @@ pipeline.
|
|||
|
||||
.. value:: merge
|
||||
|
||||
Uses the default git merge strategy (recursive).
|
||||
Uses the default git merge strategy (recursive). This maps to
|
||||
the merge mode ``merge`` in Github.
|
||||
|
||||
.. value:: merge-resolve
|
||||
|
||||
Uses the resolve git merge strategy. This is a very
|
||||
conservative merge strategy which most closely matches the
|
||||
behavior of Gerrit.
|
||||
behavior of Gerrit. This maps to the merge mode ``merge`` in
|
||||
Github.
|
||||
|
||||
.. value:: cherry-pick
|
||||
|
||||
Cherry-picks each change onto the branch rather than
|
||||
performing any merges.
|
||||
performing any merges. This is not supported by Github.
|
||||
|
||||
.. attr:: vars
|
||||
:default: None
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
features:
|
||||
- |
|
||||
It is now possible to select the merge method GitHub uses to merge a Pull
|
||||
Request to the base branch.
|
|
@ -1271,9 +1271,9 @@ class FakeGithubConnection(githubconnection.GithubConnection):
|
|||
pull_request.addComment(message)
|
||||
|
||||
def mergePull(self, project, pr_number, commit_message='', sha=None,
|
||||
zuul_event_id=None):
|
||||
method='merge', zuul_event_id=None):
|
||||
# record that this got reported
|
||||
self.reports.append((project, pr_number, 'merge'))
|
||||
self.reports.append((project, pr_number, 'merge', method))
|
||||
pull_request = self.pull_requests[int(pr_number)]
|
||||
if self.merge_failure:
|
||||
raise Exception('Pull request was not merged')
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
- pipeline:
|
||||
name: gate
|
||||
manager: dependent
|
||||
trigger:
|
||||
github:
|
||||
- event: pull_request
|
||||
action:
|
||||
- opened
|
||||
- changed
|
||||
- reopened
|
||||
branch: ^master$
|
||||
success:
|
||||
github:
|
||||
status: success
|
||||
merge: true
|
||||
failure:
|
||||
github: {}
|
||||
|
||||
- job:
|
||||
name: base
|
||||
parent: null
|
||||
run: playbooks/base.yaml
|
||||
|
||||
- job:
|
||||
name: project-test1
|
||||
run: playbooks/project-test1.yaml
|
||||
|
||||
- job:
|
||||
name: project-test2
|
||||
run: playbooks/project-test2.yaml
|
||||
|
||||
- project:
|
||||
name: org/project
|
||||
merge-mode: cherry-pick
|
||||
gate:
|
||||
jobs:
|
||||
- project-test1
|
||||
- project-test2
|
|
@ -1097,6 +1097,35 @@ class TestGithubDriver(ZuulTestCase):
|
|||
MatchesRegex(r'.*\[project-test2 \]\(.*\).*', re.DOTALL))
|
||||
self.assertEqual(2, len(self.history))
|
||||
|
||||
@simple_layout('layouts/gate-github-cherry-pick.yaml', driver='github')
|
||||
def test_merge_method_cherry_pick(self):
|
||||
"""
|
||||
Tests that the merge mode gets forwarded to the reporter and the
|
||||
merge fails because cherry-pick is not supported by github.
|
||||
"""
|
||||
github = self.fake_github.getGithubClient()
|
||||
github._data.required_contexts[('org/project', 'master')] = [
|
||||
'tenant-one/check',
|
||||
'tenant-one/gate']
|
||||
|
||||
A = self.fake_github.openFakePullRequest('org/project', 'master', 'A')
|
||||
self.fake_github.emitEvent(A.getPullRequestOpenedEvent())
|
||||
self.waitUntilSettled()
|
||||
|
||||
repo = github.repo_from_project('org/project')
|
||||
repo.create_status(A.head_sha, 'success', 'example.com', 'description',
|
||||
'tenant-one/check')
|
||||
|
||||
self.fake_github.emitEvent(A.getPullRequestOpenedEvent())
|
||||
self.waitUntilSettled()
|
||||
|
||||
# the change should have entered the gate
|
||||
self.assertEqual(2, len(self.history))
|
||||
|
||||
self.assertEqual(2, len(A.comments))
|
||||
self.assertFalse(A.is_merged)
|
||||
self.assertIn('Merge Failed', A.comments[1])
|
||||
|
||||
|
||||
class TestGithubUnprotectedBranches(ZuulTestCase):
|
||||
config_file = 'zuul-github-driver.conf'
|
||||
|
|
|
@ -1420,13 +1420,14 @@ class GithubConnection(BaseConnection):
|
|||
self.log_rate_limit(self.log, github)
|
||||
|
||||
def mergePull(self, project, pr_number, commit_message='', sha=None,
|
||||
zuul_event_id=None):
|
||||
method='merge', zuul_event_id=None):
|
||||
log = get_annotated_logger(self.log, zuul_event_id)
|
||||
github = self.getGithubClient(project, zuul_event_id=zuul_event_id)
|
||||
github = self.getGithubClient(project)
|
||||
owner, proj = project.split('/')
|
||||
pull_request = github.pull_request(owner, proj, pr_number)
|
||||
try:
|
||||
result = pull_request.merge(commit_message=commit_message, sha=sha)
|
||||
result = pull_request.merge(commit_message=commit_message, sha=sha,
|
||||
merge_method=method)
|
||||
except github3.exceptions.MethodNotAllowed as e:
|
||||
raise MergeFailure('Merge was not successful due to mergeability'
|
||||
' conflict, original error is %s' % e)
|
||||
|
|
|
@ -17,6 +17,7 @@ import voluptuous as v
|
|||
import time
|
||||
|
||||
from zuul.lib.logutil import get_annotated_logger
|
||||
from zuul.model import MERGER_MERGE_RESOLVE, MERGER_MERGE, MERGER_MAP
|
||||
from zuul.reporter import BaseReporter
|
||||
from zuul.exceptions import MergeFailure
|
||||
from zuul.driver.util import scalar_or_list
|
||||
|
@ -29,6 +30,12 @@ class GithubReporter(BaseReporter):
|
|||
name = 'github'
|
||||
log = logging.getLogger("zuul.GithubReporter")
|
||||
|
||||
# Merge modes supported by github
|
||||
merge_modes = {
|
||||
MERGER_MERGE: 'merge',
|
||||
MERGER_MERGE_RESOLVE: 'merge',
|
||||
}
|
||||
|
||||
def __init__(self, driver, connection, pipeline, config=None):
|
||||
super(GithubReporter, self).__init__(driver, connection, config)
|
||||
self._commit_status = self.config.get('status', None)
|
||||
|
@ -136,6 +143,15 @@ class GithubReporter(BaseReporter):
|
|||
|
||||
def mergePull(self, item):
|
||||
log = get_annotated_logger(self.log, item.event)
|
||||
merge_mode = item.current_build_set.getMergeMode()
|
||||
|
||||
if merge_mode not in self.merge_modes:
|
||||
mode = [x[0] for x in MERGER_MAP.items() if x[1] == merge_mode][0]
|
||||
self.log.warning('Merge mode %s not supported by Github', mode)
|
||||
# TODO(tobiash): report error to user
|
||||
return
|
||||
|
||||
merge_mode = self.merge_modes[merge_mode]
|
||||
project = item.change.project.name
|
||||
pr_number = item.change.number
|
||||
sha = item.change.patchset
|
||||
|
@ -145,7 +161,8 @@ class GithubReporter(BaseReporter):
|
|||
|
||||
for i in [1, 2]:
|
||||
try:
|
||||
self.connection.mergePull(project, pr_number, message, sha,
|
||||
self.connection.mergePull(project, pr_number, message, sha=sha,
|
||||
method=merge_mode,
|
||||
zuul_event_id=item.event)
|
||||
item.change.is_merged = True
|
||||
return
|
||||
|
|
Loading…
Reference in New Issue