Implement github pipeline req of current-patchset
Require that the commit from the event is the latest commit in the pull request. Also fix a problem with faked github status grabs. Now we're sending an event where the sha of the event isn't the head sha, and that was tripping up our fakes. Change-Id: I269c97d096e42f0a2d4a0f1b0e57eb238e0b7baf
This commit is contained in:
parent
4a27f135a6
commit
0d40c127c7
|
@ -996,8 +996,12 @@ class FakeGithubConnection(githubconnection.GithubConnection):
|
|||
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
|
||||
pr.head_sha == sha):
|
||||
sha in pr.statuses):
|
||||
return pr.statuses[sha]
|
||||
|
||||
def setCommitStatus(self, project, sha, state,
|
||||
|
|
|
@ -154,6 +154,20 @@
|
|||
github:
|
||||
comment: true
|
||||
|
||||
- pipeline:
|
||||
name: require_current
|
||||
manager: independent
|
||||
require:
|
||||
github:
|
||||
current-patchset: true
|
||||
trigger:
|
||||
github:
|
||||
- event: pull_request
|
||||
action: changed
|
||||
success:
|
||||
github:
|
||||
comment: true
|
||||
|
||||
- job:
|
||||
name: project1-pipeline
|
||||
- job:
|
||||
|
@ -170,6 +184,8 @@
|
|||
name: project7-olderthan
|
||||
- job:
|
||||
name: project8-requireopen
|
||||
- job:
|
||||
name: project9-requirecurrent
|
||||
|
||||
- project:
|
||||
name: org/project1
|
||||
|
@ -221,3 +237,9 @@
|
|||
require_open:
|
||||
jobs:
|
||||
- project8-requireopen
|
||||
|
||||
- project:
|
||||
name: org/project9
|
||||
require_current:
|
||||
jobs:
|
||||
- project9-requirecurrent
|
||||
|
|
|
@ -307,3 +307,22 @@ class TestGithubRequirements(ZuulTestCase):
|
|||
self.waitUntilSettled()
|
||||
# PR is closed, should not trigger
|
||||
self.assertEqual(len(self.history), 1)
|
||||
|
||||
@simple_layout('layouts/requirements-github.yaml', driver='github')
|
||||
def test_require_current(self):
|
||||
|
||||
A = self.fake_github.openFakePullRequest('org/project9', 'master', 'A')
|
||||
# A sync event that we will keep submitting to trigger
|
||||
sync = A.getPullRequestSynchronizeEvent()
|
||||
self.fake_github.emitEvent(sync)
|
||||
self.waitUntilSettled()
|
||||
|
||||
# PR head is current should enqueue
|
||||
self.assertEqual(len(self.history), 1)
|
||||
|
||||
# Add a commit to the PR, re-issue the original comment event
|
||||
A.addCommit()
|
||||
self.fake_github.emitEvent(sync)
|
||||
self.waitUntilSettled()
|
||||
# Event hash is not current, should not trigger
|
||||
self.assertEqual(len(self.history), 1)
|
||||
|
|
|
@ -480,6 +480,9 @@ class GithubConnection(BaseConnection):
|
|||
change.reviews = self.getPullReviews(project, change.number)
|
||||
change.source_event = event
|
||||
change.open = self.getPullOpen(project, change.number)
|
||||
change.is_current_patchset = self.getIsCurrent(project,
|
||||
change.number,
|
||||
event.patch_number)
|
||||
elif event.ref:
|
||||
change = Ref(project)
|
||||
change.ref = event.ref
|
||||
|
@ -721,6 +724,10 @@ class GithubConnection(BaseConnection):
|
|||
pr = self.getPull(project, number)
|
||||
return pr.get('state') == 'open'
|
||||
|
||||
def getIsCurrent(self, project, number, sha):
|
||||
pr = self.getPull(project, number)
|
||||
return pr.get('head').get('sha') == sha
|
||||
|
||||
def _ghTimestampToDate(self, timestamp):
|
||||
return time.strptime(timestamp, '%Y-%m-%dT%H:%M:%SZ')
|
||||
|
||||
|
|
|
@ -263,13 +263,15 @@ class GithubEventFilter(EventFilter, GithubCommonFilter):
|
|||
|
||||
|
||||
class GithubRefFilter(RefFilter, GithubCommonFilter):
|
||||
def __init__(self, statuses=[], required_reviews=[], open=None):
|
||||
def __init__(self, statuses=[], required_reviews=[], open=None,
|
||||
current_patchset=None):
|
||||
RefFilter.__init__(self)
|
||||
|
||||
GithubCommonFilter.__init__(self, required_reviews=required_reviews,
|
||||
required_statuses=statuses)
|
||||
self.statuses = statuses
|
||||
self.open = open
|
||||
self.current_patchset = current_patchset
|
||||
|
||||
def __repr__(self):
|
||||
ret = '<GithubRefFilter'
|
||||
|
@ -281,6 +283,8 @@ class GithubRefFilter(RefFilter, GithubCommonFilter):
|
|||
str(self.required_reviews))
|
||||
if self.open:
|
||||
ret += ' open: %s' % self.open
|
||||
if self.current_patchset:
|
||||
ret += ' current-patchset: %s' % self.current_patchset
|
||||
|
||||
ret += '>'
|
||||
|
||||
|
@ -294,6 +298,10 @@ class GithubRefFilter(RefFilter, GithubCommonFilter):
|
|||
if self.open != change.open:
|
||||
return False
|
||||
|
||||
if self.current_patchset is not None:
|
||||
if self.current_patchset != change.is_current_patchset:
|
||||
return False
|
||||
|
||||
# required reviews are ANDed
|
||||
if not self.matchesReviews(change):
|
||||
return False
|
||||
|
|
|
@ -99,6 +99,7 @@ class GithubSource(BaseSource):
|
|||
statuses=to_list(config.get('status')),
|
||||
required_reviews=to_list(config.get('review')),
|
||||
open=config.get('open'),
|
||||
current_patchset=config.get('current-patchset'),
|
||||
)
|
||||
return [f]
|
||||
|
||||
|
@ -118,7 +119,8 @@ review = v.Schema({'username': str,
|
|||
def getRequireSchema():
|
||||
require = {'status': scalar_or_list(str),
|
||||
'review': scalar_or_list(review),
|
||||
'open': bool}
|
||||
'open': bool,
|
||||
'current-patchset': bool}
|
||||
return require
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue