Merge "Fix multiple prs found when commit is not head"

This commit is contained in:
Zuul 2020-09-28 00:56:38 +00:00 committed by Gerrit Code Review
commit 8a357bfcf8
4 changed files with 49 additions and 16 deletions

View File

@ -1930,7 +1930,8 @@ class FakeGithubPullRequest(object):
def __init__(self, github, number, project, branch,
subject, upstream_root, files=[], number_of_commits=1,
writers=[], body=None, body_text=None, draft=False):
writers=[], body=None, body_text=None, draft=False,
base_sha=None):
"""Creates a new PR with several commits.
Sends an event about opened PR."""
self.github = github
@ -1957,7 +1958,7 @@ class FakeGithubPullRequest(object):
self.merge_message = None
self.state = 'open'
self.url = 'https://%s/%s/pull/%s' % (github.server, project, number)
self._createPRRef()
self._createPRRef(base_sha=base_sha)
self._addCommitToRepo(files=files)
self._updateTimeStamp()
@ -2124,10 +2125,11 @@ class FakeGithubPullRequest(object):
repo_path = os.path.join(self.upstream_root, self.project)
return git.Repo(repo_path)
def _createPRRef(self):
def _createPRRef(self, base_sha=None):
base_sha = base_sha or 'refs/tags/init'
repo = self._getRepo()
GithubChangeReference.create(
repo, self.getPRReference(), 'refs/tags/init')
repo, self.getPRReference(), base_sha)
def _addCommitToRepo(self, files=[], reset=False):
repo = self._getRepo()
@ -2380,11 +2382,13 @@ class FakeGithubConnection(githubconnection.GithubConnection):
self.zuul_web_port = port
def openFakePullRequest(self, project, branch, subject, files=[],
body=None, body_text=None, draft=False):
body=None, body_text=None, draft=False,
base_sha=None):
self.pr_number += 1
pull_request = FakeGithubPullRequest(
self, self.pr_number, project, branch, subject, self.upstream_root,
files=files, body=body, body_text=body_text, draft=draft)
files=files, body=body, body_text=body_text, draft=draft,
base_sha=base_sha)
self.pull_requests[self.pr_number] = pull_request
return pull_request

View File

@ -757,9 +757,24 @@ class FakeGithubClient(object):
return re.match(r'[a-z0-9]{40}', s)
if query_is_sha(query):
return (FakeIssueSearchResult(FakeIssue(pr))
for pr in self._data.pull_requests.values()
if pr.head_sha == query)
# Github returns all PR's that contain the sha in their history
result = []
for pr in self._data.pull_requests.values():
# Quick check if head sha matches
if pr.head_sha == query:
result.append(FakeIssueSearchResult(FakeIssue(pr)))
continue
# If head sha doesn't match it still could be in the pr history
repo = pr._getRepo()
commits = repo.iter_commits(
'%s...%s' % (pr.branch, pr.head_sha))
for commit in commits:
if commit.hexsha == query:
result.append(FakeIssueSearchResult(FakeIssue(pr)))
continue
return result
# Non-SHA queries are of the form:
#

View File

@ -92,6 +92,11 @@ class TestGithubRequirements(ZuulTestCase):
project = 'org/project2'
A = self.fake_github.openFakePullRequest(project, 'master', 'A')
# Create second PR which contains the head of A in its history. Zuul
# should not get disturbed by the existence of this one.
self.fake_github.openFakePullRequest(
project, 'master', 'A', base_sha=A.head_sha)
# An error status should not cause it to be enqueued
self.fake_github.setCommitStatus(project, A.head_sha, 'error',
context='tenant-one/check')

View File

@ -1703,16 +1703,25 @@ class GithubConnection(BaseConnection):
issues = list(github.search_issues(sha))
log.debug('Got PR on project %s for sha %s', project_name, sha)
if len(issues) > 1:
raise Exception('Multiple pulls found with head sha %s' % sha)
if len(issues) == 0:
return None
pr_body = self._getChange(
project, issues.pop().issue.number, sha, event=event).pr
self._sha_pr_cache.update(project_name, pr_body)
return pr_body
# Github returns all issues that contain the sha, not only the ones
# with that sha as head_sha so we need to get and update all those
# changes and then filter for the head sha before we can error out
# with multiple pulls found.
found_pr_body = None
for item in issues:
pr_body = self._getChange(
project, item.issue.number, sha, event=event).pr
self._sha_pr_cache.update(project_name, pr_body)
if pr_body['head']['sha'] == sha:
if found_pr_body:
raise Exception(
'Multiple pulls found with head sha %s' % sha)
found_pr_body = pr_body
return found_pr_body
def getPullReviews(self, pr_obj, project, number, event):
log = get_annotated_logger(self.log, event)