Support for github commit status
Github reporter sets commit status of pull request based on the result
of the pipeline.
Change-Id: Id95bf0dbaa710c555e3a1838d3430e18ac9501aa
Co-Authored-By: Jesse Keating <omgjlk@us.ibm.com>
diff --git a/tests/base.py b/tests/base.py
index 56b1269..0ad1ec1 100755
--- a/tests/base.py
+++ b/tests/base.py
@@ -556,6 +556,7 @@
self.branch = branch
self.upstream_root = upstream_root
self.comments = []
+ self.statuses = {}
self.updated_at = None
self.head_sha = None
self._createPRRef()
@@ -566,11 +567,13 @@
"""Adds a commit on top of the actual PR head."""
self._addCommitToRepo()
self._updateTimeStamp()
+ self._clearStatuses()
def forcePush(self):
"""Clears actual commits and add a commit on top of the base."""
self._addCommitToRepo(reset=True)
self._updateTimeStamp()
+ self._clearStatuses()
def getPullRequestOpenedEvent(self):
return self._getPullRequestEvent('opened')
@@ -644,6 +647,16 @@
repo = self._getRepo()
return repo.references[self._getPRReference()].commit.hexsha
+ def setStatus(self, state, url, description, context):
+ self.statuses[context] = {
+ 'state': state,
+ 'url': url,
+ 'description': description
+ }
+
+ def _clearStatuses(self):
+ self.statuses = {}
+
def _getPRReference(self):
return '%s/head' % self.number
@@ -745,10 +758,19 @@
# just returns master for now
return ['master']
- def report(self, project, pr_number, message, params=None):
+ def commentPull(self, project, pr_number, message):
pull_request = self.pull_requests[pr_number - 1]
pull_request.addComment(message)
+ def setCommitStatus(self, project, sha, state,
+ url='', description='', context=''):
+ owner, proj = project.split('/')
+ for pr in self.pull_requests:
+ pr_owner, pr_project = pr.project.split('/')
+ if (pr_owner == owner and pr_project == proj and
+ pr.head_sha == sha):
+ pr.setStatus(state, url, description, context)
+
class BuildHistory(object):
def __init__(self, **kw):
diff --git a/tests/fixtures/layouts/reporting-github.yaml b/tests/fixtures/layouts/reporting-github.yaml
new file mode 100644
index 0000000..bcbac1b
--- /dev/null
+++ b/tests/fixtures/layouts/reporting-github.yaml
@@ -0,0 +1,45 @@
+- pipeline:
+ name: check
+ description: Standard check
+ manager: independent
+ trigger:
+ github:
+ - event: pull_request
+ action: opened
+ start:
+ github:
+ status: 'pending'
+ comment: false
+ success:
+ github:
+ status: 'success'
+
+- pipeline:
+ name: reporting
+ description: Uncommon reporting
+ manager: independent
+ trigger:
+ github:
+ - event: pull_request
+ action: comment
+ comment: 'reporting check'
+ start:
+ github: {}
+ success:
+ github:
+ comment: false
+ failure:
+ github:
+ comment: false
+
+- job:
+ name: project-test1
+
+- project:
+ name: org/project
+ check:
+ jobs:
+ - project-test1
+ reporting:
+ jobs:
+ - project-test1
diff --git a/tests/fixtures/zuul-github-driver.conf b/tests/fixtures/zuul-github-driver.conf
index b4a85f7..58c7cd5 100644
--- a/tests/fixtures/zuul-github-driver.conf
+++ b/tests/fixtures/zuul-github-driver.conf
@@ -3,6 +3,7 @@
[zuul]
job_name_in_report=true
+status_url=http://zuul.example.com/status
[merger]
git_dir=/tmp/zuul-test/git
diff --git a/tests/unit/test_github_driver.py b/tests/unit/test_github_driver.py
index 1e5f6a6..9017ce9 100644
--- a/tests/unit/test_github_driver.py
+++ b/tests/unit/test_github_driver.py
@@ -13,6 +13,8 @@
# under the License.
import logging
+import re
+from testtools.matchers import MatchesRegex
from tests.base import ZuulTestCase, simple_layout, random_sha1
@@ -122,3 +124,44 @@
"""Test that git_ssh option gives git url with ssh"""
url = self.fake_github_ssh.real_getGitUrl('org/project')
self.assertEqual('ssh://git@github.com/org/project.git', url)
+
+ @simple_layout('layouts/reporting-github.yaml', driver='github')
+ def test_reporting(self):
+ # pipeline reports pull status both on start and success
+ self.executor_server.hold_jobs_in_build = True
+ pr = self.fake_github.openFakePullRequest('org/project', 'master')
+ self.fake_github.emitEvent(pr.getPullRequestOpenedEvent())
+ self.waitUntilSettled()
+ self.assertIn('check', pr.statuses)
+ check_status = pr.statuses['check']
+ self.assertEqual('Standard check', check_status['description'])
+ self.assertEqual('pending', check_status['state'])
+ self.assertEqual('http://zuul.example.com/status', check_status['url'])
+ self.assertEqual(0, len(pr.comments))
+
+ self.executor_server.hold_jobs_in_build = False
+ self.executor_server.release()
+ self.waitUntilSettled()
+ check_status = pr.statuses['check']
+ self.assertEqual('Standard check', check_status['description'])
+ self.assertEqual('success', check_status['state'])
+ self.assertEqual('http://zuul.example.com/status', check_status['url'])
+ self.assertEqual(1, len(pr.comments))
+ self.assertThat(pr.comments[0],
+ MatchesRegex('.*Build succeeded.*', re.DOTALL))
+
+ # pipeline does not report any status but does comment
+ self.executor_server.hold_jobs_in_build = True
+ self.fake_github.emitEvent(
+ pr.getCommentAddedEvent('reporting check'))
+ self.waitUntilSettled()
+ self.assertNotIn('reporting', pr.statuses)
+ # comments increased by one for the start message
+ self.assertEqual(2, len(pr.comments))
+ self.assertThat(pr.comments[1],
+ MatchesRegex('.*Starting reporting jobs.*', re.DOTALL))
+ self.executor_server.hold_jobs_in_build = False
+ self.executor_server.release()
+ self.waitUntilSettled()
+ self.assertNotIn('reporting', pr.statuses)
+ self.assertEqual(2, len(pr.comments))