5 * Copyright (c) 2002-2011, Sebastian Bergmann <sebastian@phpunit.de>.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
15 * * Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
20 * * Neither the name of Sebastian Bergmann nor the names of his
21 * contributors may be used to endorse or promote products derived
22 * from this software without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
38 * @subpackage Extensions_TicketListener
39 * @author Raphael Stolt <raphael.stolt@gmail.com>
40 * @copyright 2002-2011 Sebastian Bergmann <sebastian@phpunit.de>
41 * @license http://www.opensource.org/licenses/bsd-license.php BSD License
42 * @link http://www.phpunit.de/
43 * @since File available since Release 3.5.0
47 * A ticket listener that interacts with the GitHub issue API.
50 * @subpackage Extensions_TicketListener
51 * @author Raphael Stolt <raphael.stolt@gmail.com>
52 * @copyright 2002-2011 Sebastian Bergmann <sebastian@phpunit.de>
53 * @license http://www.opensource.org/licenses/bsd-license.php BSD License
54 * @version Release: 3.5.14
55 * @link http://www.phpunit.de/
56 * @since Class available since Release 3.5.0
58 class PHPUnit_Extensions_TicketListener_GitHub extends PHPUnit_Extensions_TicketListener
60 const STATUS_CLOSE = 'closed';
61 const STATUS_REOPEN = 'reopened';
66 private $apiPath = 'http://github.com/api/v2/json/issues';
67 private $printTicketStateChanges;
70 * @param string $username The username associated with the GitHub account.
71 * @param string $apiToken The API token associated with the GitHub account.
72 * @param string $repository The repository of the system under test (SUT) on GitHub.
73 * @param string $printTicketChanges Boolean flag to print the ticket state
74 * changes in the test result.
75 * @throws RuntimeException
77 public function __construct($username, $apiToken, $repository, $printTicketStateChanges = FALSE)
79 if (!extension_loaded('curl')) {
80 throw new RuntimeException('ext/curl is not available');
83 if (!extension_loaded('json')) {
84 throw new RuntimeException('ext/json is not available');
87 $this->username = $username;
88 $this->apiToken = $apiToken;
89 $this->repository = $repository;
90 $this->printTicketStateChanges = $printTicketStateChanges;
94 * @param integer $ticketId
96 * @throws RuntimeException
98 public function getTicketInfo($ticketId = NULL)
100 if (!is_numeric($ticketId)) {
101 return array('status' => 'invalid_ticket_id');
104 $ticket = $this->callGitHub(
105 $this->apiPath . '/show/' . $this->username . '/' .
106 $this->repository . '/' . $ticketId,
110 if ($ticket['state'] === 'open') {
111 return array('status' => 'new');
114 if ($ticket['state'] === 'closed') {
115 return array('status' => 'closed');
118 if ($ticket['state'] === 'unknown_ticket') {
119 return array('status' => 'unknown_ticket');
124 * @param string $ticketId The ticket number of the ticket under test (TUT).
125 * @param string $statusToBe The status of the TUT after running the associated test.
126 * @param string $message The additional message for the TUT.
127 * @param string $resolution The resolution for the TUT.
128 * @throws RuntimeException
130 protected function updateTicket($ticketId, $statusToBe, $message, $resolution)
132 $acceptedResponseIssueStates = array('open', 'closed');
134 if ($statusToBe === self::STATUS_CLOSE) {
135 $apiEndpoint = $this->apiPath . '/close/' .
136 $this->username . '/' . $this->repository . '/' .
140 else if ($statusToBe === self::STATUS_REOPEN) {
141 $apiEndpoint = $this->apiPath . '/reopen/' .
142 $this->username . '/' . $this->repository . '/' .
146 if (isset($apiEndpoint)) {
147 $ticket = $this->callGitHub($apiEndpoint);
149 if (!in_array($ticket['state'], $acceptedResponseIssueStates)) {
150 throw new RuntimeException(
151 'Received an unaccepted issue state from the GitHub Api'
155 if ($this->printTicketStateChanges) {
157 "\nUpdating GitHub issue #%d, status: %s\n",
166 * @param string $apiEndpoint API endpoint to call against the GitHub issue API.
167 * @param boolean $isShowMethodCall Show method of the GitHub issue API is called?
169 * @throws RuntimeException
171 private function callGitHub($apiEndpoint, $isShowMethodCall = FALSE)
173 $curlHandle = curl_init();
175 curl_setopt($curlHandle, CURLOPT_URL, $apiEndpoint);
176 curl_setopt($curlHandle, CURLOPT_FOLLOWLOCATION, TRUE);
177 curl_setopt($curlHandle, CURLOPT_FAILONERROR, TRUE);
178 curl_setopt($curlHandle, CURLOPT_FRESH_CONNECT, TRUE);
179 curl_setopt($curlHandle, CURLOPT_RETURNTRANSFER, TRUE);
180 curl_setopt($curlHandle, CURLOPT_HTTPPROXYTUNNEL, TRUE);
181 curl_setopt($curlHandle, CURLOPT_USERAGENT, __CLASS__);
185 'login=' . $this->username . '&token=' . $this->apiToken
188 $response = curl_exec($curlHandle);
190 if (!$response && $isShowMethodCall) {
191 return array('state' => 'unknown_ticket');
195 throw new RuntimeException(curl_error($curlHandle));
198 curl_close($curlHandle);
200 $issue = (array)json_decode($response);
202 return (array)$issue['issue'];