Allow check runs to be configured as required status in pipeline config
Although commit checks and statuses can only be retrieved via their respective APIs, Github does not differentiate between both in terms of branch protection and in the status section (below the comments of a PR). To mimic this behaviour in Zuul, one can now configure a check run as required status in the pipeline config. Change-Id: Ia5757c476bcee6082991928ab7c1743d0200d04a
This commit is contained in:
parent
98a8ebe890
commit
07cf1e1a6e
|
@ -499,6 +499,21 @@ enqueued into the pipeline.
|
||||||
request. The syntax is ``user:status:value``. This can also
|
request. The syntax is ``user:status:value``. This can also
|
||||||
be a regular expression.
|
be a regular expression.
|
||||||
|
|
||||||
|
Zuul does not differentiate between a status reported via
|
||||||
|
status API or via checks API (which is also how Github behaves
|
||||||
|
in terms of branch protection and `status checks`__).
|
||||||
|
Thus, the status could be reported by a
|
||||||
|
:attr:`pipeline.<reporter>.<github source>.status` or a
|
||||||
|
:attr:`pipeline.<reporter>.<github source>.check`.
|
||||||
|
|
||||||
|
When a status is reported via the status API, Github will add
|
||||||
|
a ``[bot]`` to the name of the app that reported the status,
|
||||||
|
resulting in something like ``user[bot]:status:value``. For a
|
||||||
|
status reported via the checks API, the app's slug will be
|
||||||
|
used as is.
|
||||||
|
|
||||||
|
.. __: https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/about-status-checks#types-of-status-checks-on-github
|
||||||
|
|
||||||
.. attr:: label
|
.. attr:: label
|
||||||
|
|
||||||
A string value indicating that the pull request must have the
|
A string value indicating that the pull request must have the
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
The status pipeline requirements of the Github driver
|
||||||
|
:attr:`pipeline.require.<github source>.status` now also matches
|
||||||
|
on statuses reported via the Github checks API.
|
|
@ -88,6 +88,25 @@
|
||||||
comment: true
|
comment: true
|
||||||
check: success
|
check: success
|
||||||
|
|
||||||
|
- pipeline:
|
||||||
|
name: require_check_run
|
||||||
|
manager: independent
|
||||||
|
require:
|
||||||
|
github:
|
||||||
|
status:
|
||||||
|
# Github does not differentiate between status and check run
|
||||||
|
# in case of branch protection and required status checks.
|
||||||
|
- check-run:tenant-one/check:success
|
||||||
|
trigger:
|
||||||
|
github:
|
||||||
|
- event: pull_request
|
||||||
|
action: comment
|
||||||
|
comment: trigger me
|
||||||
|
success:
|
||||||
|
github:
|
||||||
|
check: success
|
||||||
|
|
||||||
|
|
||||||
- pipeline:
|
- pipeline:
|
||||||
name: trigger
|
name: trigger
|
||||||
manager: independent
|
manager: independent
|
||||||
|
@ -367,6 +386,10 @@
|
||||||
name: project15-check-run
|
name: project15-check-run
|
||||||
run: playbooks/project15-check-run.yaml
|
run: playbooks/project15-check-run.yaml
|
||||||
|
|
||||||
|
- job:
|
||||||
|
name: project16-require-check-run
|
||||||
|
run: playbooks/project16-require-check-run.yaml
|
||||||
|
|
||||||
- project:
|
- project:
|
||||||
name: org/project1
|
name: org/project1
|
||||||
pipeline:
|
pipeline:
|
||||||
|
@ -465,3 +488,9 @@
|
||||||
trigger_check_run:
|
trigger_check_run:
|
||||||
jobs:
|
jobs:
|
||||||
- project15-check-run
|
- project15-check-run
|
||||||
|
|
||||||
|
- project:
|
||||||
|
name: org/project16
|
||||||
|
require_check_run:
|
||||||
|
jobs:
|
||||||
|
- project16-require-check-run
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from tests.base import ZuulTestCase, simple_layout
|
from tests.base import ZuulGithubAppTestCase, ZuulTestCase, simple_layout
|
||||||
|
|
||||||
|
|
||||||
class TestGithubRequirements(ZuulTestCase):
|
class TestGithubRequirements(ZuulTestCase):
|
||||||
|
@ -588,3 +588,46 @@ class TestGithubRequirements(ZuulTestCase):
|
||||||
self.waitUntilSettled()
|
self.waitUntilSettled()
|
||||||
self.assertEqual(len(self.history), 2)
|
self.assertEqual(len(self.history), 2)
|
||||||
self.assertEqual(self.history[1].name, 'project12-status')
|
self.assertEqual(self.history[1].name, 'project12-status')
|
||||||
|
|
||||||
|
|
||||||
|
class TestGithubAppRequirements(ZuulGithubAppTestCase):
|
||||||
|
"""Test pipeline and trigger requirements with app authentication"""
|
||||||
|
config_file = 'zuul-github-driver.conf'
|
||||||
|
|
||||||
|
@simple_layout("layouts/requirements-github.yaml", driver="github")
|
||||||
|
def test_pipeline_require_check_run(self):
|
||||||
|
"Test pipeline requirement: status (reported via a check run)"
|
||||||
|
project = "org/project16"
|
||||||
|
github = self.fake_github.getGithubClient()
|
||||||
|
repo = github.repo_from_project(project)
|
||||||
|
|
||||||
|
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)
|
||||||
|
self.waitUntilSettled()
|
||||||
|
|
||||||
|
# No status from zuul, so nothing should be enqueued
|
||||||
|
self.assertEqual(len(self.history), 0)
|
||||||
|
|
||||||
|
# An error check run should also not cause it to be enqueued
|
||||||
|
repo.create_check_run(
|
||||||
|
A.head_sha,
|
||||||
|
"tenant-one/check",
|
||||||
|
conclusion="failure",
|
||||||
|
app="check-run",
|
||||||
|
)
|
||||||
|
self.fake_github.emitEvent(comment)
|
||||||
|
self.waitUntilSettled()
|
||||||
|
self.assertEqual(len(self.history), 0)
|
||||||
|
|
||||||
|
# A success check run goes in, ready to be enqueued
|
||||||
|
repo.create_check_run(
|
||||||
|
A.head_sha,
|
||||||
|
"tenant-one/check",
|
||||||
|
conclusion="success",
|
||||||
|
app="check-run",
|
||||||
|
)
|
||||||
|
self.fake_github.emitEvent(comment)
|
||||||
|
self.waitUntilSettled()
|
||||||
|
self.assertEqual(len(self.history), 1)
|
||||||
|
|
|
@ -2085,6 +2085,17 @@ class GithubConnection(BaseConnection):
|
||||||
statuses.append("%s:%s:%s" % stuple)
|
statuses.append("%s:%s:%s" % stuple)
|
||||||
seen.append("%s:%s" % (stuple[0], stuple[1]))
|
seen.append("%s:%s" % (stuple[0], stuple[1]))
|
||||||
|
|
||||||
|
# Although Github differentiates commit statuses and commit checks via
|
||||||
|
# their respective APIs, the branch protection the status section
|
||||||
|
# (below the comments of a PR) do not differentiate between both. Thus,
|
||||||
|
# to mimic this behaviour also in Zuul, a required_status in the
|
||||||
|
# pipeline config could map to either a status or a check.
|
||||||
|
for check in self.getCommitChecks(project.name, sha, event):
|
||||||
|
ctuple = _check_as_tuple(check)
|
||||||
|
if "{}:{}".format(ctuple[0], ctuple[1]) not in seen:
|
||||||
|
statuses.append("{}:{}:{}".format(*ctuple))
|
||||||
|
seen.append("{}:{}".format(ctuple[0], ctuple[1]))
|
||||||
|
|
||||||
return statuses
|
return statuses
|
||||||
|
|
||||||
def getWebController(self, zuul_web):
|
def getWebController(self, zuul_web):
|
||||||
|
|
Loading…
Reference in New Issue