Merge "Add a test to verify push reports only set status" into feature/zuulv3
diff --git a/tests/base.py b/tests/base.py
index ff1f531..2ea98ad 100755
--- a/tests/base.py
+++ b/tests/base.py
@@ -868,6 +868,7 @@
         self.upstream_root = upstream_root
         self.merge_failure = False
         self.merge_not_allowed_count = 0
+        self.reports = []
 
     def openFakePullRequest(self, project, branch, subject, files=[]):
         self.pr_number += 1
@@ -980,10 +981,14 @@
         return ['master']
 
     def commentPull(self, project, pr_number, message):
+        # record that this got reported
+        self.reports.append((project, pr_number, 'comment'))
         pull_request = self.pull_requests[pr_number - 1]
         pull_request.addComment(message)
 
     def mergePull(self, project, pr_number, commit_message='', sha=None):
+        # record that this got reported
+        self.reports.append((project, pr_number, 'merge'))
         pull_request = self.pull_requests[pr_number - 1]
         if self.merge_failure:
             raise Exception('Pull request was not merged')
@@ -999,6 +1004,8 @@
 
     def setCommitStatus(self, project, sha, state, url='', description='',
                         context='default', user='zuul'):
+        # record that this got reported
+        self.reports.append((project, sha, 'status', (user, context, state)))
         # always insert a status to the front of the list, to represent
         # the last status provided for a commit.
         # Since we're bypassing github API, which would require a user, we
@@ -1015,10 +1022,14 @@
         })
 
     def labelPull(self, project, pr_number, label):
+        # record that this got reported
+        self.reports.append((project, pr_number, 'label', label))
         pull_request = self.pull_requests[pr_number - 1]
         pull_request.addLabel(label)
 
     def unlabelPull(self, project, pr_number, label):
+        # record that this got reported
+        self.reports.append((project, pr_number, 'unlabel', label))
         pull_request = self.pull_requests[pr_number - 1]
         pull_request.removeLabel(label)
 
diff --git a/tests/fixtures/layouts/reporting-github.yaml b/tests/fixtures/layouts/reporting-github.yaml
index d054df7..0fdec85 100644
--- a/tests/fixtures/layouts/reporting-github.yaml
+++ b/tests/fixtures/layouts/reporting-github.yaml
@@ -34,6 +34,29 @@
       github:
         comment: false
 
+- pipeline:
+    name: push-reporting
+    description: Uncommon reporting
+    manager: independent
+    trigger:
+      github:
+        - event: push
+        - event: pull_request
+          action: opened
+    start:
+      github:
+        comment: true
+        status: 'pending'
+    success:
+      github:
+        comment: true
+        status: 'success'
+        merge: true
+    failure:
+      github:
+        comment: true
+        status: 'failure'
+
 - job:
     name: project-test1
 
@@ -45,3 +68,9 @@
     reporting:
       jobs:
         - project-test1
+
+- project:
+    name: org/project2
+    push-reporting:
+      jobs:
+        - project-test1
diff --git a/tests/unit/test_github_driver.py b/tests/unit/test_github_driver.py
index ba8e497..a19073c 100644
--- a/tests/unit/test_github_driver.py
+++ b/tests/unit/test_github_driver.py
@@ -320,6 +320,46 @@
         self.assertThat(report_status['url'][len(base):],
                         MatchesRegex('^[a-fA-F0-9]{32}\/$'))
 
+    @simple_layout('layouts/reporting-github.yaml', driver='github')
+    def test_push_reporting(self):
+        project = 'org/project2'
+        # pipeline reports pull status both on start and success
+        self.executor_server.hold_jobs_in_build = True
+        pevent = self.fake_github.getPushEvent(project=project,
+                                               ref='refs/heads/master')
+
+        self.fake_github.emitEvent(pevent)
+        self.waitUntilSettled()
+
+        # there should only be one report, a status
+        self.assertEqual(1, len(self.fake_github.reports))
+        # Verify the user/context/state of the status
+        status = ('zuul', 'tenant-one/push-reporting', 'pending')
+        self.assertEqual(status, self.fake_github.reports[0][-1])
+
+        # free the executor, allow the build to finish
+        self.executor_server.hold_jobs_in_build = False
+        self.executor_server.release()
+        self.waitUntilSettled()
+
+        # Now there should be a second report, the success of the build
+        self.assertEqual(2, len(self.fake_github.reports))
+        # Verify the user/context/state of the status
+        status = ('zuul', 'tenant-one/push-reporting', 'success')
+        self.assertEqual(status, self.fake_github.reports[-1][-1])
+
+        # now make a PR which should also comment
+        self.executor_server.hold_jobs_in_build = True
+        A = self.fake_github.openFakePullRequest(project, 'master', 'A')
+        self.fake_github.emitEvent(A.getPullRequestOpenedEvent())
+        self.waitUntilSettled()
+
+        # Now there should be a four reports, a new comment
+        # and status
+        self.assertEqual(4, len(self.fake_github.reports))
+        self.executor_server.release()
+        self.waitUntilSettled()
+
     @simple_layout('layouts/merging-github.yaml', driver='github')
     def test_report_pull_merge(self):
         # pipeline merges the pull request on success
diff --git a/zuul/driver/github/githubreporter.py b/zuul/driver/github/githubreporter.py
index 37cbe61..94f0393 100644
--- a/zuul/driver/github/githubreporter.py
+++ b/zuul/driver/github/githubreporter.py
@@ -43,10 +43,13 @@
         """Report on an event."""
         # order is important for github branch protection.
         # A status should be set before a merge attempt
-        if (self._commit_status is not None and
-            hasattr(item.change, 'patchset') and
-            item.change.patchset is not None):
-            self.setCommitStatus(item)
+        if self._commit_status is not None:
+            if (hasattr(item.change, 'patchset') and
+                    item.change.patchset is not None):
+                self.setCommitStatus(item)
+            elif (hasattr(item.change, 'newrev') and
+                    item.change.newrev is not None):
+                self.setCommitStatus(item)
         # Comments, labels, and merges can only be performed on pull requests.
         # If the change is not a pull request (e.g. a push) skip them.
         if hasattr(item.change, 'number'):
@@ -71,7 +74,10 @@
 
     def setCommitStatus(self, item):
         project = item.change.project.name
-        sha = item.change.patchset
+        if hasattr(item.change, 'patchset'):
+            sha = item.change.patchset
+        elif hasattr(item.change, 'newrev'):
+            sha = item.change.newrev
         context = '%s/%s' % (item.pipeline.layout.tenant.name,
                              item.pipeline.name)
         state = self._commit_status