Improve fake github commit status handling
Move the commit status handling from directly in fake pull request
objects to be part of the fake github object, to more closely model how
github itself works.
Change-Id: I195f7bad8ee499a48de57fa0d2bbb7a736f7b343
Story: 2000774
Task: 4609
diff --git a/tests/base.py b/tests/base.py
index 76f7e03..fae23fe 100755
--- a/tests/base.py
+++ b/tests/base.py
@@ -776,21 +776,6 @@
repo = self._getRepo()
return repo.references[self._getPRReference()].commit.hexsha
- def setStatus(self, sha, state, url, description, context, user='zuul'):
- # Since we're bypassing github API, which would require a user, we
- # hard set the user as 'zuul' here.
- # insert the status at the top of the list, to simulate that it
- # is the most recent set status
- self.statuses[sha].insert(0, ({
- 'state': state,
- 'url': url,
- 'description': description,
- 'context': context,
- 'creator': {
- 'login': user
- }
- }))
-
def addReview(self, user, state, granted_on=None):
gh_time_format = '%Y-%m-%dT%H:%M:%SZ'
# convert the timestamp to a str format that would be returned
@@ -882,6 +867,7 @@
self.connection_name = connection_name
self.pr_number = 0
self.pull_requests = []
+ self.statuses = {}
self.upstream_root = upstream_root
self.merge_failure = False
self.merge_not_allowed_count = 0
@@ -1014,25 +1000,24 @@
pull_request.merge_message = commit_message
def getCommitStatuses(self, project, sha):
- owner, proj = project.split('/')
- for pr in self.pull_requests:
- pr_owner, pr_project = pr.project.split('/')
- # This is somewhat risky, if the same commit exists in multiple
- # PRs, we might grab the wrong one that doesn't have a status
- # that is expected to be there. Maybe re-work this so that there
- # is a global registry of commit statuses like with github.
- if (pr_owner == owner and pr_project == proj and
- sha in pr.statuses):
- return pr.statuses[sha]
+ return self.statuses.get(project, {}).get(sha, [])
- def setCommitStatus(self, project, sha, state,
- url='', description='', context=''):
- owner, proj = project.split('/')
- for pr in self.pull_requests:
- pr_owner, pr_project = pr.project.split('/')
- if (pr_owner == owner and pr_project == proj and
- pr.head_sha == sha):
- pr.setStatus(sha, state, url, description, context)
+ def setCommitStatus(self, project, sha, state, url='', description='',
+ context='default', user='zuul'):
+ # always insert a status to the front of the list, to represent
+ # the last status provided for a commit.
+ # Since we're bypassing github API, which would require a user, we
+ # default the user as 'zuul' here.
+ self.statuses.setdefault(project, {}).setdefault(sha, [])
+ self.statuses[project][sha].insert(0, {
+ 'state': state,
+ 'url': url,
+ 'description': description,
+ 'context': context,
+ 'creator': {
+ 'login': user
+ }
+ })
def labelPull(self, project, pr_number, label):
pull_request = self.pull_requests[pr_number - 1]
diff --git a/tests/unit/test_github_driver.py b/tests/unit/test_github_driver.py
index 4979087..ba8e497 100644
--- a/tests/unit/test_github_driver.py
+++ b/tests/unit/test_github_driver.py
@@ -248,16 +248,18 @@
@simple_layout('layouts/reporting-github.yaml', driver='github')
def test_reporting(self):
+ project = 'org/project'
# pipeline reports pull status both on start and success
self.executor_server.hold_jobs_in_build = True
- A = self.fake_github.openFakePullRequest('org/project', 'master', 'A')
+ A = self.fake_github.openFakePullRequest(project, 'master', 'A')
self.fake_github.emitEvent(A.getPullRequestOpenedEvent())
self.waitUntilSettled()
# We should have a status container for the head sha
- self.assertIn(A.head_sha, A.statuses.keys())
+ statuses = self.fake_github.statuses[project][A.head_sha]
+ self.assertIn(A.head_sha, self.fake_github.statuses[project].keys())
# We should only have one status for the head sha
- self.assertEqual(1, len(A.statuses[A.head_sha]))
- check_status = A.statuses[A.head_sha][0]
+ self.assertEqual(1, len(statuses))
+ check_status = statuses[0]
check_url = ('http://zuul.example.com/status/#%s,%s' %
(A.number, A.head_sha))
self.assertEqual('tenant-one/check', check_status['context'])
@@ -270,8 +272,9 @@
self.executor_server.release()
self.waitUntilSettled()
# We should only have two statuses for the head sha
- self.assertEqual(2, len(A.statuses[A.head_sha]))
- check_status = A.statuses[A.head_sha][0]
+ statuses = self.fake_github.statuses[project][A.head_sha]
+ self.assertEqual(2, len(statuses))
+ check_status = statuses[0]
check_url = ('http://zuul.example.com/status/#%s,%s' %
(A.number, A.head_sha))
self.assertEqual('tenant-one/check', check_status['context'])
@@ -286,7 +289,8 @@
self.fake_github.emitEvent(
A.getCommentAddedEvent('reporting check'))
self.waitUntilSettled()
- self.assertEqual(2, len(A.statuses[A.head_sha]))
+ statuses = self.fake_github.statuses[project][A.head_sha]
+ self.assertEqual(2, len(statuses))
# comments increased by one for the start message
self.assertEqual(2, len(A.comments))
self.assertThat(A.comments[1],
@@ -295,8 +299,9 @@
self.executor_server.release()
self.waitUntilSettled()
# pipeline reports success status
- self.assertEqual(3, len(A.statuses[A.head_sha]))
- report_status = A.statuses[A.head_sha][0]
+ statuses = self.fake_github.statuses[project][A.head_sha]
+ self.assertEqual(3, len(statuses))
+ report_status = statuses[0]
self.assertEqual('tenant-one/reporting', report_status['context'])
self.assertEqual('success', report_status['state'])
self.assertEqual(2, len(A.comments))
diff --git a/tests/unit/test_github_requirements.py b/tests/unit/test_github_requirements.py
index 5dd6e80..301ea2f 100644
--- a/tests/unit/test_github_requirements.py
+++ b/tests/unit/test_github_requirements.py
@@ -25,7 +25,8 @@
@simple_layout('layouts/requirements-github.yaml', driver='github')
def test_pipeline_require_status(self):
"Test pipeline requirement: status"
- A = self.fake_github.openFakePullRequest('org/project1', 'master', 'A')
+ project = 'org/project1'
+ A = self.fake_github.openFakePullRequest(project, 'master', 'A')
# A comment event that we will keep submitting to trigger
comment = A.getCommentAddedEvent('test me')
self.fake_github.emitEvent(comment)
@@ -34,13 +35,15 @@
self.assertEqual(len(self.history), 0)
# An error status should not cause it to be enqueued
- A.setStatus(A.head_sha, 'error', 'null', 'null', 'check')
+ self.fake_github.setCommitStatus(project, A.head_sha, 'error',
+ context='check')
self.fake_github.emitEvent(comment)
self.waitUntilSettled()
self.assertEqual(len(self.history), 0)
# A success status goes in
- A.setStatus(A.head_sha, 'success', 'null', 'null', 'check')
+ self.fake_github.setCommitStatus(project, A.head_sha, 'success',
+ context='check')
self.fake_github.emitEvent(comment)
self.waitUntilSettled()
self.assertEqual(len(self.history), 1)
@@ -49,7 +52,8 @@
@simple_layout('layouts/requirements-github.yaml', driver='github')
def test_trigger_require_status(self):
"Test trigger requirement: status"
- A = self.fake_github.openFakePullRequest('org/project1', 'master', 'A')
+ project = 'org/project1'
+ A = self.fake_github.openFakePullRequest(project, 'master', 'A')
# A comment event that we will keep submitting to trigger
comment = A.getCommentAddedEvent('trigger me')
self.fake_github.emitEvent(comment)
@@ -58,13 +62,15 @@
self.assertEqual(len(self.history), 0)
# An error status should not cause it to be enqueued
- A.setStatus(A.head_sha, 'error', 'null', 'null', 'check')
+ self.fake_github.setCommitStatus(project, A.head_sha, 'error',
+ context='check')
self.fake_github.emitEvent(comment)
self.waitUntilSettled()
self.assertEqual(len(self.history), 0)
# A success status goes in
- A.setStatus(A.head_sha, 'success', 'null', 'null', 'check')
+ self.fake_github.setCommitStatus(project, A.head_sha, 'success',
+ context='check')
self.fake_github.emitEvent(comment)
self.waitUntilSettled()
self.assertEqual(len(self.history), 1)
@@ -73,10 +79,12 @@
@simple_layout('layouts/requirements-github.yaml', driver='github')
def test_trigger_on_status(self):
"Test trigger on: status"
- A = self.fake_github.openFakePullRequest('org/project2', 'master', 'A')
+ project = 'org/project2'
+ A = self.fake_github.openFakePullRequest(project, 'master', 'A')
# An error status should not cause it to be enqueued
- A.setStatus(A.head_sha, 'error', 'null', 'null', 'check')
+ self.fake_github.setCommitStatus(project, A.head_sha, 'error',
+ context='check')
self.fake_github.emitEvent(A.getCommitStatusEvent('check',
state='error'))
self.waitUntilSettled()
@@ -84,7 +92,8 @@
# A success status from unknown user should not cause it to be
# enqueued
- A.setStatus(A.head_sha, 'success', 'null', 'null', 'check', user='foo')
+ self.fake_github.setCommitStatus(project, A.head_sha, 'success',
+ context='check', user='foo')
self.fake_github.emitEvent(A.getCommitStatusEvent('check',
state='success',
user='foo'))
@@ -92,7 +101,8 @@
self.assertEqual(len(self.history), 0)
# A success status from zuul goes in
- A.setStatus(A.head_sha, 'success', 'null', 'null', 'check')
+ self.fake_github.setCommitStatus(project, A.head_sha, 'success',
+ context='check')
self.fake_github.emitEvent(A.getCommitStatusEvent('check'))
self.waitUntilSettled()
self.assertEqual(len(self.history), 1)
@@ -100,7 +110,8 @@
# An error status for a different context should not cause it to be
# enqueued
- A.setStatus(A.head_sha, 'error', 'null', 'null', 'gate')
+ self.fake_github.setCommitStatus(project, A.head_sha, 'error',
+ context='gate')
self.fake_github.emitEvent(A.getCommitStatusEvent('gate',
state='error'))
self.waitUntilSettled()