summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelix Edel <felix.edel@bmw.de>2020-03-04 15:37:28 +0100
committerFelix Edel <felix.edel@bmw.de>2020-05-12 16:48:16 +0200
commit07cf1e1a6e11181b1abebc35067a9aa20bef4e47 (patch)
tree3d267d373e0ba4bc70f644d077b8c2c84e74ece0
parent98a8ebe8901909cc4f5faba8ec2a21300fb297b9 (diff)
downloadzuul-07cf1e1a6e11181b1abebc35067a9aa20bef4e47.tar.gz
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
-rw-r--r--doc/source/reference/drivers/github.rst15
-rw-r--r--releasenotes/notes/github-require-check-294d3f27da790fae.yaml6
-rw-r--r--tests/fixtures/layouts/requirements-github.yaml29
-rw-r--r--tests/unit/test_github_requirements.py45
-rw-r--r--zuul/driver/github/githubconnection.py11
5 files changed, 105 insertions, 1 deletions
diff --git a/doc/source/reference/drivers/github.rst b/doc/source/reference/drivers/github.rst
index 474c8ac82..c2c085eca 100644
--- a/doc/source/reference/drivers/github.rst
+++ b/doc/source/reference/drivers/github.rst
@@ -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
diff --git a/releasenotes/notes/github-require-check-294d3f27da790fae.yaml b/releasenotes/notes/github-require-check-294d3f27da790fae.yaml
new file mode 100644
index 000000000..a01d59b20
--- /dev/null
+++ b/releasenotes/notes/github-require-check-294d3f27da790fae.yaml
@@ -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.
diff --git a/tests/fixtures/layouts/requirements-github.yaml b/tests/fixtures/layouts/requirements-github.yaml
index f5fa0f5de..9e376b8b6 100644
--- a/tests/fixtures/layouts/requirements-github.yaml
+++ b/tests/fixtures/layouts/requirements-github.yaml
@@ -89,6 +89,25 @@
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
trigger:
@@ -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
diff --git a/tests/unit/test_github_requirements.py b/tests/unit/test_github_requirements.py
index 461df55da..e542f80f9 100644
--- a/tests/unit/test_github_requirements.py
+++ b/tests/unit/test_github_requirements.py
@@ -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)
diff --git a/zuul/driver/github/githubconnection.py b/zuul/driver/github/githubconnection.py
index 19497008d..a054d9e49 100644
--- a/zuul/driver/github/githubconnection.py
+++ b/zuul/driver/github/githubconnection.py
@@ -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):