Use combined status for Github status checks

When checking the required status checks we currently get all statuses
and get the successful of them. However Github returns all historic
status changes there. So a change that get a successful check, then a
recheck and then a failed check still enters the gate but will be
prohibited by Github to merge in the end. However github also offers
us a combined status call that only returns the current state of the
statuses. Using this fixes the issue.

Change-Id: Iec3b2a3dfc8626870381604badd40de71e7257b9
This commit is contained in:
Tobias Henkel 2018-12-07 08:50:43 +01:00
parent ced4584c43
commit 9fa93fdefa
No known key found for this signature in database
GPG Key ID: 03750DEC158E5FA2
3 changed files with 39 additions and 3 deletions

View File

@ -59,6 +59,12 @@ class FakeStatus(object):
}
class FakeCombinedStatus(object):
def __init__(self, sha, statuses):
self.sha = sha
self.statuses = statuses
class FakeCommit(object):
def __init__(self, sha):
self._statuses = []
@ -74,6 +80,19 @@ class FakeCommit(object):
def statuses(self):
return self._statuses
def status(self):
'''
Returns the combined status wich only contains the latest statuses of
the commit together with some other information that we don't need
here.
'''
latest_statuses_by_context = {}
for status in self._statuses:
if status.context not in latest_statuses_by_context:
latest_statuses_by_context[status.context] = status
combined_statuses = latest_statuses_by_context.values()
return FakeCombinedStatus(self.sha, combined_statuses)
class FakeRepository(object):
def __init__(self, name, data):

View File

@ -896,8 +896,25 @@ class TestGithubDriver(ZuulTestCase):
# job is expected
self.assertEqual(0, len(self.history))
# now set the required status 'tenant-one/check'
# now set a failing status 'tenant-one/check'
repo = github.repo_from_project('org/project')
repo.create_status(A.head_sha, 'failed', 'example.com', 'description',
'tenant-one/check')
self.fake_github.emitEvent(A.getPullRequestOpenedEvent())
self.waitUntilSettled()
self.assertEqual(0, len(self.history))
# now set a successful status followed by a failing status to check
# that the later failed status wins
repo.create_status(A.head_sha, 'success', 'example.com', 'description',
'tenant-one/check')
repo.create_status(A.head_sha, 'failed', 'example.com', 'description',
'tenant-one/check')
self.fake_github.emitEvent(A.getPullRequestOpenedEvent())
self.waitUntilSettled()
self.assertEqual(0, len(self.history))
# now set the required status 'tenant-one/check'
repo.create_status(A.head_sha, 'success', 'example.com', 'description',
'tenant-one/check')

View File

@ -1245,8 +1245,8 @@ class GithubConnection(BaseConnection):
break
# Get successful statuses
successful = set(
[s.context for s in commit.statuses() if s.state == 'success'])
successful = set([s.context for s in commit.status().statuses
if s.state == 'success'])
# Required contexts must be a subset of the successful contexts as
# we allow additional successful status contexts we don't care about.