2013-05-16 00:47:37 +02:00
|
|
|
<?php
|
|
|
|
/**
|
2014-05-12 18:26:17 +02:00
|
|
|
* PHPCI - Continuous Integration for PHP
|
|
|
|
*
|
|
|
|
* @copyright Copyright 2014, Block 8 Limited.
|
|
|
|
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
|
|
|
|
* @link https://www.phptesting.org/
|
|
|
|
*/
|
2013-05-16 00:47:37 +02:00
|
|
|
|
|
|
|
namespace PHPCI\Model\Build;
|
2013-05-16 16:40:40 +02:00
|
|
|
|
2014-05-12 16:18:42 +02:00
|
|
|
use PHPCI\Builder;
|
2015-02-20 14:37:36 +01:00
|
|
|
use PHPCI\Helper\Diff;
|
|
|
|
use PHPCI\Helper\Github;
|
2013-05-16 00:47:37 +02:00
|
|
|
use PHPCI\Model\Build\RemoteGitBuild;
|
|
|
|
|
|
|
|
/**
|
2013-05-16 03:30:48 +02:00
|
|
|
* Github Build Model
|
|
|
|
* @author Dan Cryer <dan@block8.co.uk>
|
|
|
|
* @package PHPCI
|
|
|
|
* @subpackage Core
|
|
|
|
*/
|
2013-05-16 00:47:37 +02:00
|
|
|
class GithubBuild extends RemoteGitBuild
|
|
|
|
{
|
2013-05-16 18:17:29 +02:00
|
|
|
/**
|
|
|
|
* Get link to commit from another source (i.e. Github)
|
|
|
|
*/
|
2013-05-16 16:40:40 +02:00
|
|
|
public function getCommitLink()
|
|
|
|
{
|
|
|
|
return 'https://github.com/' . $this->getProject()->getReference() . '/commit/' . $this->getCommitId();
|
|
|
|
}
|
2013-05-16 00:47:37 +02:00
|
|
|
|
2013-05-16 18:17:29 +02:00
|
|
|
/**
|
|
|
|
* Get link to branch from another source (i.e. Github)
|
|
|
|
*/
|
2013-05-16 16:40:40 +02:00
|
|
|
public function getBranchLink()
|
|
|
|
{
|
|
|
|
return 'https://github.com/' . $this->getProject()->getReference() . '/tree/' . $this->getBranch();
|
|
|
|
}
|
2013-05-16 00:47:37 +02:00
|
|
|
|
2013-05-16 18:17:29 +02:00
|
|
|
/**
|
|
|
|
* Send status updates to any relevant third parties (i.e. Github)
|
|
|
|
*/
|
2013-05-16 16:40:40 +02:00
|
|
|
public function sendStatusPostback()
|
|
|
|
{
|
2013-10-11 22:51:23 +02:00
|
|
|
$token = \b8\Config::getInstance()->get('phpci.github.token');
|
2013-05-16 00:47:37 +02:00
|
|
|
|
2015-10-05 15:41:13 +02:00
|
|
|
if (empty($token) || empty($this->data['id'])) {
|
2013-05-16 16:40:40 +02:00
|
|
|
return;
|
|
|
|
}
|
2013-05-16 00:47:37 +02:00
|
|
|
|
2013-10-11 22:51:23 +02:00
|
|
|
$project = $this->getProject();
|
|
|
|
|
2015-10-05 15:41:13 +02:00
|
|
|
if (empty($project)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-05-16 16:40:40 +02:00
|
|
|
$url = 'https://api.github.com/repos/'.$project->getReference().'/statuses/'.$this->getCommitId();
|
|
|
|
$http = new \b8\HttpClient();
|
2013-05-16 00:47:37 +02:00
|
|
|
|
2015-10-05 15:17:13 +02:00
|
|
|
switch ($this->getStatus()) {
|
2013-05-16 16:40:40 +02:00
|
|
|
case 0:
|
|
|
|
case 1:
|
|
|
|
$status = 'pending';
|
2015-10-02 22:35:53 +02:00
|
|
|
$description = 'PHPCI build running.';
|
2013-05-16 16:40:40 +02:00
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
$status = 'success';
|
2015-10-02 22:35:53 +02:00
|
|
|
$description = 'PHPCI build passed.';
|
2013-05-16 16:40:40 +02:00
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
$status = 'failure';
|
2015-10-02 22:35:53 +02:00
|
|
|
$description = 'PHPCI build failed.';
|
2013-05-16 16:40:40 +02:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
$status = 'error';
|
2015-10-02 22:35:53 +02:00
|
|
|
$description = 'PHPCI build failed to complete.';
|
2013-05-16 16:40:40 +02:00
|
|
|
break;
|
|
|
|
}
|
2013-05-16 00:47:37 +02:00
|
|
|
|
2013-10-10 02:30:40 +02:00
|
|
|
$phpciUrl = \b8\Config::getInstance()->get('phpci.url');
|
2015-10-02 22:35:53 +02:00
|
|
|
|
|
|
|
$params = array(
|
|
|
|
'state' => $status,
|
|
|
|
'target_url' => $phpciUrl . '/build/view/' . $this->getId(),
|
|
|
|
'description' => $description,
|
|
|
|
'context' => 'PHPCI',
|
|
|
|
);
|
|
|
|
|
2013-05-16 16:40:40 +02:00
|
|
|
$headers = array(
|
2013-10-11 22:51:23 +02:00
|
|
|
'Authorization: token ' . $token,
|
2013-05-16 16:40:40 +02:00
|
|
|
'Content-Type: application/x-www-form-urlencoded'
|
2015-10-02 22:35:53 +02:00
|
|
|
);
|
2013-05-16 00:47:37 +02:00
|
|
|
|
2013-05-16 16:40:40 +02:00
|
|
|
$http->setHeaders($headers);
|
2013-10-10 02:30:40 +02:00
|
|
|
$http->request('POST', $url, json_encode($params));
|
2013-05-16 16:40:40 +02:00
|
|
|
}
|
2013-05-16 00:47:37 +02:00
|
|
|
|
2013-05-16 18:17:29 +02:00
|
|
|
/**
|
|
|
|
* Get the URL to be used to clone this remote repository.
|
|
|
|
*/
|
2013-05-16 16:40:40 +02:00
|
|
|
protected function getCloneUrl()
|
|
|
|
{
|
2014-05-13 17:15:33 +02:00
|
|
|
$key = trim($this->getProject()->getSshPrivateKey());
|
2013-05-16 00:47:37 +02:00
|
|
|
|
2013-05-16 16:40:40 +02:00
|
|
|
if (!empty($key)) {
|
|
|
|
return 'git@github.com:' . $this->getProject()->getReference() . '.git';
|
|
|
|
} else {
|
|
|
|
return 'https://github.com/' . $this->getProject()->getReference() . '.git';
|
|
|
|
}
|
|
|
|
}
|
2014-04-25 13:28:27 +02:00
|
|
|
|
2014-12-08 12:25:33 +01:00
|
|
|
/**
|
|
|
|
* Get a parsed version of the commit message, with links to issues and commits.
|
|
|
|
* @return string
|
|
|
|
*/
|
2014-04-25 13:28:27 +02:00
|
|
|
public function getCommitMessage()
|
|
|
|
{
|
2015-01-31 10:23:29 +01:00
|
|
|
$rtn = parent::getCommitMessage($this->data['commit_message']);
|
2014-04-25 13:28:27 +02:00
|
|
|
|
2015-10-05 15:41:13 +02:00
|
|
|
$project = $this->getProject();
|
|
|
|
|
|
|
|
if (!is_null($project)) {
|
|
|
|
$reference = $project->getReference();
|
|
|
|
$commitLink = '<a target="_blank" href="https://github.com/' . $reference . '/issues/$1">#$1</a>';
|
|
|
|
$rtn = preg_replace('/\#([0-9]+)/', $commitLink, $rtn);
|
|
|
|
$rtn = preg_replace('/\@([a-zA-Z0-9_]+)/', '<a target="_blank" href="https://github.com/$1">@$1</a>', $rtn);
|
|
|
|
}
|
2014-04-25 13:28:27 +02:00
|
|
|
|
|
|
|
return $rtn;
|
|
|
|
}
|
|
|
|
|
2014-12-08 12:25:33 +01:00
|
|
|
/**
|
|
|
|
* Get a template to use for generating links to files.
|
|
|
|
* e.g. https://github.com/block8/phpci/blob/master/{FILE}#L{LINE}
|
|
|
|
* @return string
|
|
|
|
*/
|
2014-04-25 13:28:27 +02:00
|
|
|
public function getFileLinkTemplate()
|
|
|
|
{
|
2014-07-29 18:19:37 +02:00
|
|
|
$reference = $this->getProject()->getReference();
|
|
|
|
$branch = $this->getBranch();
|
|
|
|
|
|
|
|
if ($this->getExtra('build_type') == 'pull_request') {
|
|
|
|
$matches = array();
|
2015-02-26 19:59:49 +01:00
|
|
|
preg_match('/[\/:]([a-zA-Z0-9_\-]+\/[a-zA-Z0-9_\-]+)/', $this->getExtra('remote_url'), $matches);
|
2014-07-29 18:19:37 +02:00
|
|
|
|
|
|
|
$reference = $matches[1];
|
|
|
|
$branch = $this->getExtra('remote_branch');
|
|
|
|
}
|
|
|
|
|
|
|
|
$link = 'https://github.com/' . $reference . '/';
|
|
|
|
$link .= 'blob/' . $branch . '/';
|
2014-04-25 13:28:27 +02:00
|
|
|
$link .= '{FILE}';
|
|
|
|
$link .= '#L{LINE}';
|
|
|
|
|
|
|
|
return $link;
|
|
|
|
}
|
2014-05-12 16:18:42 +02:00
|
|
|
|
2014-12-08 12:25:33 +01:00
|
|
|
/**
|
|
|
|
* Handle any post-clone tasks, like applying a pull request patch on top of the branch.
|
|
|
|
* @param Builder $builder
|
|
|
|
* @param $cloneTo
|
|
|
|
* @return bool
|
|
|
|
*/
|
2014-05-12 16:18:42 +02:00
|
|
|
protected function postCloneSetup(Builder $builder, $cloneTo)
|
|
|
|
{
|
|
|
|
$buildType = $this->getExtra('build_type');
|
|
|
|
|
|
|
|
$success = true;
|
|
|
|
|
|
|
|
try {
|
|
|
|
if (!empty($buildType) && $buildType == 'pull_request') {
|
|
|
|
$remoteUrl = $this->getExtra('remote_url');
|
|
|
|
$remoteBranch = $this->getExtra('remote_branch');
|
|
|
|
|
2014-05-12 17:28:48 +02:00
|
|
|
$cmd = 'cd "%s" && git checkout -b phpci/' . $this->getId() . ' %s && git pull -q --no-edit %s %s';
|
2014-05-12 16:18:42 +02:00
|
|
|
$success = $builder->executeCommand($cmd, $cloneTo, $this->getBranch(), $remoteUrl, $remoteBranch);
|
|
|
|
}
|
|
|
|
} catch (\Exception $ex) {
|
|
|
|
$success = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($success) {
|
|
|
|
$success = parent::postCloneSetup($builder, $cloneTo);
|
|
|
|
}
|
|
|
|
|
|
|
|
return $success;
|
|
|
|
}
|
2015-02-20 14:37:36 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @inheritDoc
|
|
|
|
*/
|
2015-10-15 11:07:54 +02:00
|
|
|
public function reportError(
|
|
|
|
Builder $builder,
|
|
|
|
$plugin,
|
|
|
|
$message,
|
|
|
|
$severity = BuildError::SEVERITY_NORMAL,
|
|
|
|
$file = null,
|
|
|
|
$lineStart = null,
|
|
|
|
$lineEnd = null
|
|
|
|
) {
|
|
|
|
$diffLineNumber = $this->getDiffLineNumber($builder, $file, $lineStart);
|
2015-02-20 14:37:36 +01:00
|
|
|
|
|
|
|
if (!is_null($diffLineNumber)) {
|
|
|
|
$helper = new Github();
|
|
|
|
|
|
|
|
$repo = $this->getProject()->getReference();
|
|
|
|
$prNumber = $this->getExtra('pull_request_number');
|
|
|
|
$commit = $this->getCommitId();
|
|
|
|
|
|
|
|
if (!empty($prNumber)) {
|
|
|
|
$helper->createPullRequestComment($repo, $prNumber, $commit, $file, $diffLineNumber, $message);
|
|
|
|
} else {
|
|
|
|
$helper->createCommitComment($repo, $commit, $file, $diffLineNumber, $message);
|
|
|
|
}
|
|
|
|
}
|
2015-10-15 11:07:54 +02:00
|
|
|
|
|
|
|
return parent::reportError($builder, $plugin, $message, $severity, $file, $lineStart, $lineEnd);
|
2015-02-20 14:37:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Uses git diff to figure out what the diff line position is, based on the error line number.
|
|
|
|
* @param Builder $builder
|
|
|
|
* @param $file
|
|
|
|
* @param $line
|
|
|
|
* @return int|null
|
|
|
|
*/
|
|
|
|
protected function getDiffLineNumber(Builder $builder, $file, $line)
|
|
|
|
{
|
2015-05-24 10:20:51 +02:00
|
|
|
$line = (integer)$line;
|
|
|
|
|
2015-02-20 14:37:36 +01:00
|
|
|
$builder->logExecOutput(false);
|
|
|
|
|
|
|
|
$prNumber = $this->getExtra('pull_request_number');
|
|
|
|
$path = $builder->buildPath;
|
|
|
|
|
|
|
|
if (!empty($prNumber)) {
|
|
|
|
$builder->executeCommand('cd %s && git diff origin/%s "%s"', $path, $this->getBranch(), $file);
|
|
|
|
} else {
|
2015-02-25 15:13:28 +01:00
|
|
|
$commitId = $this->getCommitId();
|
|
|
|
$compare = $commitId == 'Manual' ? 'HEAD' : $commitId;
|
2015-02-26 09:31:58 +01:00
|
|
|
$builder->executeCommand('cd %s && git diff %s^^ "%s"', $path, $compare, $file);
|
2015-02-20 14:37:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
$builder->logExecOutput(true);
|
|
|
|
|
|
|
|
$diff = $builder->getLastOutput();
|
|
|
|
|
|
|
|
$helper = new Diff();
|
|
|
|
$lines = $helper->getLinePositions($diff);
|
|
|
|
|
2015-05-27 23:20:37 +02:00
|
|
|
return isset($lines[$line]) ? $lines[$line] : null;
|
2015-02-20 14:37:36 +01:00
|
|
|
}
|
2013-05-16 00:47:37 +02:00
|
|
|
}
|