summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZuul <zuul@review.opendev.org>2020-05-12 21:15:45 +0000
committerGerrit Code Review <review@openstack.org>2020-05-12 21:15:45 +0000
commit438871db678864f2ee29767be34192120aa65d58 (patch)
treebfa1771ced2dc53bf36c0a032c2c6f05c9f2385b
parent087ab1d587cfae85a8db72463e838e00d970f0b3 (diff)
parent07cf1e1a6e11181b1abebc35067a9aa20bef4e47 (diff)
downloadzuul-438871db678864f2ee29767be34192120aa65d58.tar.gz
Merge "Allow check runs to be configured as required status in pipeline config"
-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):