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:
Felix Edel 2020-03-04 15:37:28 +01:00
parent 98a8ebe890
commit 07cf1e1a6e
No known key found for this signature in database
GPG Key ID: E95717A102DD3030
5 changed files with 105 additions and 1 deletions

View File

@ -499,6 +499,21 @@ enqueued into the pipeline.
request. The syntax is ``user:status:value``. This can also
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
A string value indicating that the pull request must have the

View File

@ -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.

View File

@ -88,6 +88,25 @@
comment: true
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:
name: trigger
manager: independent
@ -367,6 +386,10 @@
name: project15-check-run
run: playbooks/project15-check-run.yaml
- job:
name: project16-require-check-run
run: playbooks/project16-require-check-run.yaml
- project:
name: org/project1
pipeline:
@ -465,3 +488,9 @@
trigger_check_run:
jobs:
- project15-check-run
- project:
name: org/project16
require_check_run:
jobs:
- project16-require-check-run

View File

@ -14,7 +14,7 @@
import time
from tests.base import ZuulTestCase, simple_layout
from tests.base import ZuulGithubAppTestCase, ZuulTestCase, simple_layout
class TestGithubRequirements(ZuulTestCase):
@ -588,3 +588,46 @@ class TestGithubRequirements(ZuulTestCase):
self.waitUntilSettled()
self.assertEqual(len(self.history), 2)
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)

View File

@ -2085,6 +2085,17 @@ class GithubConnection(BaseConnection):
statuses.append("%s:%s:%s" % stuple)
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
def getWebController(self, zuul_web):