Big update.
This commit is contained in:
parent
dd59bff838
commit
3647ac1cd8
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -2,3 +2,4 @@
|
||||||
vendor/
|
vendor/
|
||||||
composer.lock
|
composer.lock
|
||||||
config.php
|
config.php
|
||||||
|
.DS_Store
|
||||||
|
|
|
@ -19,42 +19,49 @@ class Builder
|
||||||
public function __construct(Build $build)
|
public function __construct(Build $build)
|
||||||
{
|
{
|
||||||
$this->build = $build;
|
$this->build = $build;
|
||||||
|
$this->store = Store\Factory::getStore('Build');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function execute()
|
public function execute()
|
||||||
{
|
{
|
||||||
$this->build->setStatus(1);
|
$this->build->setStatus(1);
|
||||||
$this->build = Store\Factory::getStore('Build')->save($this->build);
|
$this->build->setStarted(new \DateTime());
|
||||||
|
$this->build = $this->store->save($this->build);
|
||||||
|
|
||||||
if($this->setupBuild())
|
if($this->setupBuild())
|
||||||
{
|
{
|
||||||
$this->executeEvent('prepare');
|
$this->executePlugins('setup');
|
||||||
$this->executePlugins();
|
$this->executePlugins('test');
|
||||||
|
|
||||||
$this->log('');
|
$this->log('');
|
||||||
|
|
||||||
$this->executeEvent('on_complete');
|
$this->executePlugins('complete');
|
||||||
|
|
||||||
if($this->success)
|
if($this->success)
|
||||||
{
|
{
|
||||||
$this->executeEvent('on_success');
|
$this->executePlugins('success');
|
||||||
$this->logSuccess('BUILD SUCCESSFUL!');
|
$this->logSuccess('BUILD SUCCESSFUL!');
|
||||||
$this->build->setStatus(2);
|
$this->build->setStatus(2);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
$this->executeEvent('on_failure');
|
$this->executePlugins('failure');
|
||||||
$this->logFailure('BUILD FAILED!');
|
$this->logFailure('BUILD FAILED!');
|
||||||
$this->build->setStatus(3);
|
$this->build->setStatus(3);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->log('');
|
$this->log('');
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$this->build->setStatus(3);
|
||||||
|
}
|
||||||
|
|
||||||
$this->removeBuild();
|
$this->removeBuild();
|
||||||
|
|
||||||
|
$this->build->setFinished(new \DateTime());
|
||||||
$this->build->setLog($this->log);
|
$this->build->setLog($this->log);
|
||||||
Store\Factory::getStore('Build')->save($this->build);
|
$this->store->save($this->build);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function executeCommand($command)
|
public function executeCommand($command)
|
||||||
|
@ -94,6 +101,9 @@ class Builder
|
||||||
$this->log .= $message;
|
$this->log .= $message;
|
||||||
print $message;
|
print $message;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->build->setLog($this->log);
|
||||||
|
$this->build = $this->store->save($this->build);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function logSuccess($message)
|
protected function logSuccess($message)
|
||||||
|
@ -106,52 +116,35 @@ class Builder
|
||||||
$this->log("\033[0;31m" . $message . "\033[0m");
|
$this->log("\033[0;31m" . $message . "\033[0m");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function executeEvent($event)
|
|
||||||
{
|
|
||||||
$this->log('RUNNING '.strtoupper($event).' ACTIONS:');
|
|
||||||
|
|
||||||
if(!isset($this->config[$event]))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(is_string($this->config[$event]))
|
|
||||||
{
|
|
||||||
if(!$this->executeCommand($this->config[$event]))
|
|
||||||
{
|
|
||||||
$this->success = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(is_array($this->config[$event]))
|
|
||||||
{
|
|
||||||
foreach($this->config[$event] as $command)
|
|
||||||
{
|
|
||||||
if(!$this->executeCommand($command))
|
|
||||||
{
|
|
||||||
$this->success = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function setupBuild()
|
protected function setupBuild()
|
||||||
{
|
{
|
||||||
$commitId = $this->build->getCommitId();
|
$commitId = $this->build->getCommitId();
|
||||||
$url = $this->build->getProject()->getGitUrl();
|
$url = $this->build->getProject()->getGitUrl();
|
||||||
$key = $this->build->getProject()->getGitKey();
|
$key = $this->build->getProject()->getGitKey();
|
||||||
|
|
||||||
|
$buildId = 'project' . $this->build->getProject()->getId() . '-build' . $this->build->getId();
|
||||||
|
|
||||||
$this->ciDir = realpath(dirname(__FILE__) . '/../') . '/';
|
$this->ciDir = realpath(dirname(__FILE__) . '/../') . '/';
|
||||||
$this->buildPath = $this->ciDir . 'build/' . $commitId . '/';
|
$this->buildPath = $this->ciDir . 'build/' . $buildId . '/';
|
||||||
$keyFile = $this->ciDir . 'build/' . $commitId . '.key';
|
|
||||||
|
|
||||||
mkdir($this->buildPath, 0777, true);
|
mkdir($this->buildPath, 0777, true);
|
||||||
|
|
||||||
|
if(!empty($key))
|
||||||
|
{
|
||||||
|
// Do an SSH clone:
|
||||||
|
$keyFile = $this->ciDir . 'build/' . $buildId . '.key';
|
||||||
file_put_contents($keyFile, $key);
|
file_put_contents($keyFile, $key);
|
||||||
chmod($keyFile, 0600);
|
chmod($keyFile, 0600);
|
||||||
$this->executeCommand('ssh-agent ssh-add '.$keyFile.' && git clone -b ' .$this->build->getBranch() . ' ' .$url.' '.$this->buildPath.' && ssh-agent -k');
|
$this->executeCommand('ssh-agent ssh-add '.$keyFile.' && git clone -b ' .$this->build->getBranch() . ' ' .$url.' '.$this->buildPath.' && ssh-agent -k');
|
||||||
unlink($keyFile);
|
unlink($keyFile);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Do an HTTP clone:
|
||||||
|
$this->executeCommand('git clone -b ' .$this->build->getBranch() . ' ' .$url.' '.$this->buildPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
file_put_contents($this->buildPath . 'phpci.yml', file_get_contents('/www/b8framework/phpci.yml'));
|
||||||
|
|
||||||
if(!is_file($this->buildPath . 'phpci.yml'))
|
if(!is_file($this->buildPath . 'phpci.yml'))
|
||||||
{
|
{
|
||||||
|
@ -186,15 +179,15 @@ class Builder
|
||||||
shell_exec('rm -Rf ' . $this->buildPath);
|
shell_exec('rm -Rf ' . $this->buildPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function executePlugins()
|
protected function executePlugins($stage)
|
||||||
{
|
{
|
||||||
foreach($this->config['plugins'] as $plugin => $options)
|
foreach($this->config[$stage] as $plugin => $options)
|
||||||
{
|
{
|
||||||
$this->log('');
|
$this->log('');
|
||||||
$this->log('RUNNING PLUGIN: ' . $plugin);
|
$this->log('RUNNING PLUGIN: ' . $plugin);
|
||||||
|
|
||||||
// Is this plugin allowed to fail?
|
// Is this plugin allowed to fail?
|
||||||
if(!isset($options['allow_failures']))
|
if($stage == 'test' && !isset($options['allow_failures']))
|
||||||
{
|
{
|
||||||
$options['allow_failures'] = false;
|
$options['allow_failures'] = false;
|
||||||
}
|
}
|
||||||
|
@ -207,7 +200,7 @@ class Builder
|
||||||
{
|
{
|
||||||
$this->logFailure('Plugin does not exist: ' . $plugin);
|
$this->logFailure('Plugin does not exist: ' . $plugin);
|
||||||
|
|
||||||
if(!$options['allow_failures'])
|
if($stage == 'test' && !$options['allow_failures'])
|
||||||
{
|
{
|
||||||
$this->success = false;
|
$this->success = false;
|
||||||
}
|
}
|
||||||
|
@ -221,7 +214,7 @@ class Builder
|
||||||
|
|
||||||
if(!$plugin->execute())
|
if(!$plugin->execute())
|
||||||
{
|
{
|
||||||
if(!$options['allow_failures'])
|
if($stage == 'test' && !$options['allow_failures'])
|
||||||
{
|
{
|
||||||
$this->success = false;
|
$this->success = false;
|
||||||
}
|
}
|
||||||
|
@ -234,7 +227,7 @@ class Builder
|
||||||
{
|
{
|
||||||
$this->logFailure('EXCEPTION: ' . $ex->getMessage());
|
$this->logFailure('EXCEPTION: ' . $ex->getMessage());
|
||||||
|
|
||||||
if(!$options['allow_failures'])
|
if($stage == 'test' && !$options['allow_failures'])
|
||||||
{
|
{
|
||||||
$this->success = false;
|
$this->success = false;
|
||||||
continue;
|
continue;
|
||||||
|
|
50
PHPCI/Controller/BitbucketController.php
Normal file
50
PHPCI/Controller/BitbucketController.php
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PHPCI\Controller;
|
||||||
|
use b8,
|
||||||
|
b8\Store,
|
||||||
|
PHPCI\Model\Build;
|
||||||
|
|
||||||
|
|
||||||
|
class BitbucketController extends b8\Controller
|
||||||
|
{
|
||||||
|
public function init()
|
||||||
|
{
|
||||||
|
$this->_buildStore = Store\Factory::getStore('Build');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function webhook($project)
|
||||||
|
{
|
||||||
|
$payload = json_decode($this->getParam('payload'), true);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$build = new Build();
|
||||||
|
$build->setProjectId($project);
|
||||||
|
$build->setCommitId($payload['after']);
|
||||||
|
$build->setStatus(0);
|
||||||
|
$build->setLog('');
|
||||||
|
$build->setCreated(new \DateTime());
|
||||||
|
$build->setBranch(str_replace('refs/heads/', '', $payload['ref']));
|
||||||
|
}
|
||||||
|
catch(\Exception $ex)
|
||||||
|
{
|
||||||
|
header('HTTP/1.1 400 Bad Request');
|
||||||
|
header('Ex: ' . $ex->getMessage());
|
||||||
|
die('FAIL');
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$this->_buildStore->save($build);
|
||||||
|
}
|
||||||
|
catch(\Exception $ex)
|
||||||
|
{
|
||||||
|
header('HTTP/1.1 500 Internal Server Error');
|
||||||
|
header('Ex: ' . $ex->getMessage());
|
||||||
|
die('FAIL');
|
||||||
|
}
|
||||||
|
|
||||||
|
die('OK');
|
||||||
|
}
|
||||||
|
}
|
76
PHPCI/Controller/BuildController.php
Normal file
76
PHPCI/Controller/BuildController.php
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PHPCI\Controller;
|
||||||
|
use b8,
|
||||||
|
PHPCI\Model\Build;
|
||||||
|
|
||||||
|
class BuildController extends b8\Controller
|
||||||
|
{
|
||||||
|
public function init()
|
||||||
|
{
|
||||||
|
$this->_buildStore = b8\Store\Factory::getStore('Build');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function view($buildId)
|
||||||
|
{
|
||||||
|
$build = $this->_buildStore->getById($buildId);
|
||||||
|
|
||||||
|
$view = new b8\View('Build');
|
||||||
|
$view->build = $build;
|
||||||
|
$view->data = $this->getBuildData($buildId);
|
||||||
|
|
||||||
|
return $view->render();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function data($buildId)
|
||||||
|
{
|
||||||
|
die($this->getBuildData($buildId));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getBuildData($buildId)
|
||||||
|
{
|
||||||
|
$build = $this->_buildStore->getById($buildId);
|
||||||
|
|
||||||
|
$data = array();
|
||||||
|
$data['status'] = (int)$build->getStatus();
|
||||||
|
$data['log'] = $this->cleanLog($build->getLog());
|
||||||
|
$data['created'] = !is_null($build->getCreated()) ? $build->getCreated()->format('Y-m-d H:i:s') : null;
|
||||||
|
$data['started'] = !is_null($build->getStarted()) ? $build->getStarted()->format('Y-m-d H:i:s') : null;
|
||||||
|
$data['finished'] = !is_null($build->getFinished()) ? $build->getFinished()->format('Y-m-d H:i:s') : null;
|
||||||
|
|
||||||
|
return json_encode($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rebuild($buildId)
|
||||||
|
{
|
||||||
|
$copy = $this->_buildStore->getById($buildId);
|
||||||
|
|
||||||
|
$build = new Build();
|
||||||
|
$build->setProjectId($copy->getProjectId());
|
||||||
|
$build->setCommitId($copy->getCommitId());
|
||||||
|
$build->setStatus(0);
|
||||||
|
$build->setBranch($copy->getBranch());
|
||||||
|
$build->setCreated(new \DateTime());
|
||||||
|
|
||||||
|
$build = $this->_buildStore->save($build);
|
||||||
|
|
||||||
|
header('Location: /build/view/' . $build->getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function delete($buildId)
|
||||||
|
{
|
||||||
|
$build = $this->_buildStore->getById($buildId);
|
||||||
|
$this->_buildStore->delete($build);
|
||||||
|
|
||||||
|
header('Location: /project/view/' . $build->getProjectId());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function cleanLog($log)
|
||||||
|
{
|
||||||
|
$log = str_replace('[0;32m', '<span style="color: green">', $log);
|
||||||
|
$log = str_replace('[0;31m', '<span style="color: red">', $log);
|
||||||
|
$log = str_replace('[0m', '</span>', $log);
|
||||||
|
|
||||||
|
return $log;
|
||||||
|
}
|
||||||
|
}
|
|
@ -24,6 +24,7 @@ class GithubController extends b8\Controller
|
||||||
$build->setCommitId($payload['after']);
|
$build->setCommitId($payload['after']);
|
||||||
$build->setStatus(0);
|
$build->setStatus(0);
|
||||||
$build->setLog('');
|
$build->setLog('');
|
||||||
|
$build->setCreated(new \DateTime());
|
||||||
$build->setBranch(str_replace('refs/heads/', '', $payload['ref']));
|
$build->setBranch(str_replace('refs/heads/', '', $payload['ref']));
|
||||||
}
|
}
|
||||||
catch(\Exception $ex)
|
catch(\Exception $ex)
|
||||||
|
|
|
@ -13,13 +13,25 @@ class IndexController extends b8\Controller
|
||||||
|
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
$builds = $this->_buildStore->getWhere(array(), 10, 0, array(), array('id' => 'DESC'));
|
|
||||||
$projects = $this->_projectStore->getWhere(array(), 50, 0, array(), array('title' => 'ASC'));
|
$projects = $this->_projectStore->getWhere(array(), 50, 0, array(), array('title' => 'ASC'));
|
||||||
|
|
||||||
$view = new b8\View('Index');
|
$view = new b8\View('Index');
|
||||||
$view->builds = $builds['items'];
|
$view->builds = $this->getLatestBuildsHtml();
|
||||||
$view->projects = $projects['items'];
|
$view->projects = $projects['items'];
|
||||||
|
|
||||||
return $view->render();
|
return $view->render();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function latest()
|
||||||
|
{
|
||||||
|
die($this->getLatestBuildsHtml());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getLatestBuildsHtml()
|
||||||
|
{
|
||||||
|
$builds = $this->_buildStore->getWhere(array(), 10, 0, array(), array('id' => 'DESC'));
|
||||||
|
$view = new b8\View('BuildsTable');
|
||||||
|
$view->builds = $builds['items'];
|
||||||
|
|
||||||
|
return $view->render();
|
||||||
|
}
|
||||||
}
|
}
|
195
PHPCI/Controller/ProjectController.php
Normal file
195
PHPCI/Controller/ProjectController.php
Normal file
|
@ -0,0 +1,195 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PHPCI\Controller;
|
||||||
|
use b8,
|
||||||
|
PHPCI\Model\Build,
|
||||||
|
PHPCI\Model\Project,
|
||||||
|
b8\Form,
|
||||||
|
b8\Registry;
|
||||||
|
|
||||||
|
class ProjectController extends b8\Controller
|
||||||
|
{
|
||||||
|
public function init()
|
||||||
|
{
|
||||||
|
$this->_buildStore = b8\Store\Factory::getStore('Build');
|
||||||
|
$this->_projectStore = b8\Store\Factory::getStore('Project');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function view($projectId)
|
||||||
|
{
|
||||||
|
$project = $this->_projectStore->getById($projectId);
|
||||||
|
$page = $this->getParam('p', 1);
|
||||||
|
$builds = $this->getLatestBuildsHtml($projectId, (($page - 1) * 10));
|
||||||
|
|
||||||
|
$view = new b8\View('Project');
|
||||||
|
$view->builds = $builds[0];
|
||||||
|
$view->total = $builds[1];
|
||||||
|
$view->project = $project;
|
||||||
|
$view->page = $page;
|
||||||
|
|
||||||
|
return $view->render();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function build($projectId)
|
||||||
|
{
|
||||||
|
$build = new Build();
|
||||||
|
$build->setProjectId($projectId);
|
||||||
|
$build->setCommitId('Manual');
|
||||||
|
$build->setStatus(0);
|
||||||
|
$build->setBranch('master');
|
||||||
|
$build->setCreated(new \DateTime());
|
||||||
|
|
||||||
|
$build = $this->_buildStore->save($build);
|
||||||
|
|
||||||
|
header('Location: /build/view/' . $build->getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function delete($id)
|
||||||
|
{
|
||||||
|
$project = $this->_projectStore->getById($id);
|
||||||
|
$this->_projectStore->delete($project);
|
||||||
|
|
||||||
|
header('Location: /');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function builds($projectId)
|
||||||
|
{
|
||||||
|
$builds = $this->getLatestBuildsHtml($projectId);
|
||||||
|
die($builds[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getLatestBuildsHtml($projectId, $start = 0)
|
||||||
|
{
|
||||||
|
$builds = $this->_buildStore->getWhere(array('project_id' => $projectId), 10, $start, array(), array('id' => 'DESC'));
|
||||||
|
$view = new b8\View('BuildsTable');
|
||||||
|
$view->builds = $builds['items'];
|
||||||
|
|
||||||
|
return array($view->render(), $builds['count']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function add()
|
||||||
|
{
|
||||||
|
$method = Registry::getInstance()->get('requestMethod');
|
||||||
|
|
||||||
|
if($method == 'POST')
|
||||||
|
{
|
||||||
|
$values = $this->getParams();
|
||||||
|
$pub = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$id = '/tmp/' . md5(microtime(true));
|
||||||
|
shell_exec('ssh-keygen -q -t rsa -b 2048 -f '.$id.' -N "" -C "deploy@phpci"');
|
||||||
|
|
||||||
|
$pub = file_get_contents($id . '.pub');
|
||||||
|
$prv = file_get_contents($id);
|
||||||
|
|
||||||
|
$values = array('key' => $prv);
|
||||||
|
}
|
||||||
|
|
||||||
|
$form = $this->projectForm($values);
|
||||||
|
|
||||||
|
if($method != 'POST' || ($method == 'POST' && !$form->validate()))
|
||||||
|
{
|
||||||
|
$view = new b8\View('ProjectForm');
|
||||||
|
$view->type = 'add';
|
||||||
|
$view->project = null;
|
||||||
|
$view->form = $form;
|
||||||
|
$view->key = $pub;
|
||||||
|
|
||||||
|
return $view->render();
|
||||||
|
}
|
||||||
|
|
||||||
|
$values = $form->getValues();
|
||||||
|
$values['git_key'] = $values['key'];
|
||||||
|
|
||||||
|
$project = new Project();
|
||||||
|
$project->setValues($values);
|
||||||
|
|
||||||
|
$project = $this->_projectStore->save($project);
|
||||||
|
|
||||||
|
header('Location: /project/view/' . $project->getId());
|
||||||
|
die;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function edit($id)
|
||||||
|
{
|
||||||
|
$method = Registry::getInstance()->get('requestMethod');
|
||||||
|
$project = $this->_projectStore->getById($id);
|
||||||
|
|
||||||
|
if($method == 'POST')
|
||||||
|
{
|
||||||
|
$values = $this->getParams();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$values = $project->getDataArray();
|
||||||
|
$values['key'] = $values['git_key'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$form = $this->projectForm($values, 'edit/' . $id);
|
||||||
|
|
||||||
|
if($method != 'POST' || ($method == 'POST' && !$form->validate()))
|
||||||
|
{
|
||||||
|
$view = new b8\View('ProjectForm');
|
||||||
|
$view->type = 'edit';
|
||||||
|
$view->project = $project;
|
||||||
|
$view->form = $form;
|
||||||
|
$view->key = null;
|
||||||
|
|
||||||
|
return $view->render();
|
||||||
|
}
|
||||||
|
|
||||||
|
$values = $form->getValues();
|
||||||
|
$values['git_key'] = $values['key'];
|
||||||
|
|
||||||
|
$project->setValues($values);
|
||||||
|
$project = $this->_projectStore->save($project);
|
||||||
|
|
||||||
|
header('Location: /project/view/' . $project->getId());
|
||||||
|
die;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function projectForm($values, $type = 'add')
|
||||||
|
{
|
||||||
|
$form = new Form();
|
||||||
|
$form->setMethod('POST');
|
||||||
|
$form->setAction('/project/' . $type);
|
||||||
|
$form->addField(new Form\Element\Csrf('csrf'));
|
||||||
|
|
||||||
|
$field = new Form\Element\Text('title');
|
||||||
|
$field->setRequired(true);
|
||||||
|
$field->setLabel('Project Title');
|
||||||
|
$field->setClass('span4');
|
||||||
|
$form->addField($field);
|
||||||
|
|
||||||
|
$field = new Form\Element\Select('type');
|
||||||
|
$field->setRequired(true);
|
||||||
|
$field->setOptions(array('github' => 'Github', 'bitbucket' => 'Bitbucket'));
|
||||||
|
$field->setLabel('Where is your project hosted?');
|
||||||
|
$field->setClass('span4');
|
||||||
|
$form->addField($field);
|
||||||
|
|
||||||
|
$field = new Form\Element\Text('reference');
|
||||||
|
$field->setRequired(true);
|
||||||
|
$field->setPattern('[a-zA-Z0-9_\-]+\/[a-zA-Z0-9_\-]+');
|
||||||
|
$field->setLabel('Repository Name on Github / Bitbucket (e.g. block8/phpci)');
|
||||||
|
$field->setClass('span4');
|
||||||
|
$form->addField($field);
|
||||||
|
|
||||||
|
$field = new Form\Element\TextArea('key');
|
||||||
|
$field->setRequired(false);
|
||||||
|
$field->setLabel('Private key to use to access repository (leave blank to use anonymous HTTP repository access)');
|
||||||
|
$field->setClass('span7');
|
||||||
|
$field->setRows(6);
|
||||||
|
$form->addField($field);
|
||||||
|
|
||||||
|
$field = new Form\Element\Submit();
|
||||||
|
$field->setValue('Save Project');
|
||||||
|
$field->setClass('btn-success');
|
||||||
|
$form->addField($field);
|
||||||
|
|
||||||
|
$form->setValues($values);
|
||||||
|
return $form;
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,6 +22,9 @@ class BuildBase extends Model
|
||||||
'status' => null,
|
'status' => null,
|
||||||
'log' => null,
|
'log' => null,
|
||||||
'branch' => null,
|
'branch' => null,
|
||||||
|
'created' => null,
|
||||||
|
'started' => null,
|
||||||
|
'finished' => null,
|
||||||
);
|
);
|
||||||
protected $_getters = array(
|
protected $_getters = array(
|
||||||
'id' => 'getId',
|
'id' => 'getId',
|
||||||
|
@ -30,6 +33,9 @@ class BuildBase extends Model
|
||||||
'status' => 'getStatus',
|
'status' => 'getStatus',
|
||||||
'log' => 'getLog',
|
'log' => 'getLog',
|
||||||
'branch' => 'getBranch',
|
'branch' => 'getBranch',
|
||||||
|
'created' => 'getCreated',
|
||||||
|
'started' => 'getStarted',
|
||||||
|
'finished' => 'getFinished',
|
||||||
|
|
||||||
'Project' => 'getProject',
|
'Project' => 'getProject',
|
||||||
|
|
||||||
|
@ -42,6 +48,9 @@ class BuildBase extends Model
|
||||||
'status' => 'setStatus',
|
'status' => 'setStatus',
|
||||||
'log' => 'setLog',
|
'log' => 'setLog',
|
||||||
'branch' => 'setBranch',
|
'branch' => 'setBranch',
|
||||||
|
'created' => 'setCreated',
|
||||||
|
'started' => 'setStarted',
|
||||||
|
'finished' => 'setFinished',
|
||||||
|
|
||||||
'Project' => 'setProject',
|
'Project' => 'setProject',
|
||||||
);
|
);
|
||||||
|
@ -93,6 +102,30 @@ class BuildBase extends Model
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
),
|
||||||
|
'created' => array(
|
||||||
|
'type' => 'datetime',
|
||||||
|
'length' => '',
|
||||||
|
'nullable' => true,
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
),
|
||||||
|
'started' => array(
|
||||||
|
'type' => 'datetime',
|
||||||
|
'length' => '',
|
||||||
|
'nullable' => true,
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
),
|
||||||
|
'finished' => array(
|
||||||
|
'type' => 'datetime',
|
||||||
|
'length' => '',
|
||||||
|
'nullable' => true,
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
public $indexes = array(
|
public $indexes = array(
|
||||||
|
@ -154,6 +187,48 @@ class BuildBase extends Model
|
||||||
return $rtn;
|
return $rtn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getCreated()
|
||||||
|
{
|
||||||
|
$rtn = $this->_data['created'];
|
||||||
|
|
||||||
|
|
||||||
|
if(!empty($rtn))
|
||||||
|
{
|
||||||
|
$rtn = new \DateTime($rtn);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return $rtn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getStarted()
|
||||||
|
{
|
||||||
|
$rtn = $this->_data['started'];
|
||||||
|
|
||||||
|
|
||||||
|
if(!empty($rtn))
|
||||||
|
{
|
||||||
|
$rtn = new \DateTime($rtn);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return $rtn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFinished()
|
||||||
|
{
|
||||||
|
$rtn = $this->_data['finished'];
|
||||||
|
|
||||||
|
|
||||||
|
if(!empty($rtn))
|
||||||
|
{
|
||||||
|
$rtn = new \DateTime($rtn);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return $rtn;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public function setId($value)
|
public function setId($value)
|
||||||
|
@ -240,6 +315,48 @@ class BuildBase extends Model
|
||||||
$this->_setModified('branch');
|
$this->_setModified('branch');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setCreated($value)
|
||||||
|
{
|
||||||
|
|
||||||
|
$this->_validateDate('Created', $value);
|
||||||
|
if($this->_data['created'] == $value)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->_data['created'] = $value;
|
||||||
|
|
||||||
|
$this->_setModified('created');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setStarted($value)
|
||||||
|
{
|
||||||
|
|
||||||
|
$this->_validateDate('Started', $value);
|
||||||
|
if($this->_data['started'] == $value)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->_data['started'] = $value;
|
||||||
|
|
||||||
|
$this->_setModified('started');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setFinished($value)
|
||||||
|
{
|
||||||
|
|
||||||
|
$this->_validateDate('Finished', $value);
|
||||||
|
if($this->_data['finished'] == $value)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->_data['finished'] = $value;
|
||||||
|
|
||||||
|
$this->_setModified('finished');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -18,14 +18,16 @@ class ProjectBase extends Model
|
||||||
protected $_data = array(
|
protected $_data = array(
|
||||||
'id' => null,
|
'id' => null,
|
||||||
'title' => null,
|
'title' => null,
|
||||||
'git_url' => null,
|
'reference' => null,
|
||||||
'git_key' => null,
|
'git_key' => null,
|
||||||
|
'type' => null,
|
||||||
);
|
);
|
||||||
protected $_getters = array(
|
protected $_getters = array(
|
||||||
'id' => 'getId',
|
'id' => 'getId',
|
||||||
'title' => 'getTitle',
|
'title' => 'getTitle',
|
||||||
'git_url' => 'getGitUrl',
|
'reference' => 'getReference',
|
||||||
'git_key' => 'getGitKey',
|
'git_key' => 'getGitKey',
|
||||||
|
'type' => 'getType',
|
||||||
|
|
||||||
|
|
||||||
);
|
);
|
||||||
|
@ -33,8 +35,9 @@ class ProjectBase extends Model
|
||||||
protected $_setters = array(
|
protected $_setters = array(
|
||||||
'id' => 'setId',
|
'id' => 'setId',
|
||||||
'title' => 'setTitle',
|
'title' => 'setTitle',
|
||||||
'git_url' => 'setGitUrl',
|
'reference' => 'setReference',
|
||||||
'git_key' => 'setGitKey',
|
'git_key' => 'setGitKey',
|
||||||
|
'type' => 'setType',
|
||||||
|
|
||||||
);
|
);
|
||||||
public $columns = array(
|
public $columns = array(
|
||||||
|
@ -54,9 +57,9 @@ class ProjectBase extends Model
|
||||||
|
|
||||||
|
|
||||||
),
|
),
|
||||||
'git_url' => array(
|
'reference' => array(
|
||||||
'type' => 'varchar',
|
'type' => 'varchar',
|
||||||
'length' => '1024',
|
'length' => '250',
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -69,6 +72,14 @@ class ProjectBase extends Model
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
),
|
||||||
|
'type' => array(
|
||||||
|
'type' => 'varchar',
|
||||||
|
'length' => '50',
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
public $indexes = array(
|
public $indexes = array(
|
||||||
|
@ -95,9 +106,9 @@ class ProjectBase extends Model
|
||||||
return $rtn;
|
return $rtn;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getGitUrl()
|
public function getReference()
|
||||||
{
|
{
|
||||||
$rtn = $this->_data['git_url'];
|
$rtn = $this->_data['reference'];
|
||||||
|
|
||||||
|
|
||||||
return $rtn;
|
return $rtn;
|
||||||
|
@ -111,6 +122,14 @@ class ProjectBase extends Model
|
||||||
return $rtn;
|
return $rtn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getType()
|
||||||
|
{
|
||||||
|
$rtn = $this->_data['type'];
|
||||||
|
|
||||||
|
|
||||||
|
return $rtn;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public function setId($value)
|
public function setId($value)
|
||||||
|
@ -141,18 +160,18 @@ class ProjectBase extends Model
|
||||||
$this->_setModified('title');
|
$this->_setModified('title');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setGitUrl($value)
|
public function setReference($value)
|
||||||
{
|
{
|
||||||
$this->_validateNotNull('GitUrl', $value);
|
$this->_validateNotNull('Reference', $value);
|
||||||
$this->_validateString('GitUrl', $value);
|
$this->_validateString('Reference', $value);
|
||||||
if($this->_data['git_url'] == $value)
|
if($this->_data['reference'] == $value)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->_data['git_url'] = $value;
|
$this->_data['reference'] = $value;
|
||||||
|
|
||||||
$this->_setModified('git_url');
|
$this->_setModified('reference');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setGitKey($value)
|
public function setGitKey($value)
|
||||||
|
@ -169,6 +188,20 @@ class ProjectBase extends Model
|
||||||
$this->_setModified('git_key');
|
$this->_setModified('git_key');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setType($value)
|
||||||
|
{
|
||||||
|
$this->_validateNotNull('Type', $value);
|
||||||
|
$this->_validateString('Type', $value);
|
||||||
|
if($this->_data['type'] == $value)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->_data['type'] = $value;
|
||||||
|
|
||||||
|
$this->_setModified('type');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -16,5 +16,21 @@ use PHPCI\Model\Base\BuildBase;
|
||||||
*/
|
*/
|
||||||
class Build extends BuildBase
|
class Build extends BuildBase
|
||||||
{
|
{
|
||||||
// This class has been left blank so that you can modify it - changes in this file will not be overwritten.
|
public function getCommitLink()
|
||||||
|
{
|
||||||
|
switch($this->getProject()->getType())
|
||||||
|
{
|
||||||
|
case 'github':
|
||||||
|
return 'https://github.com/' . $this->getProject()->getReference() . '/commit/' . $this->getCommitId();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getBranchLink()
|
||||||
|
{
|
||||||
|
switch($this->getProject()->getType())
|
||||||
|
{
|
||||||
|
case 'github':
|
||||||
|
return 'https://github.com/' . $this->getProject()->getReference() . '/tree/' . $this->getBranch();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,5 +16,23 @@ use PHPCI\Model\Base\ProjectBase;
|
||||||
*/
|
*/
|
||||||
class Project extends ProjectBase
|
class Project extends ProjectBase
|
||||||
{
|
{
|
||||||
// This class has been left blank so that you can modify it - changes in this file will not be overwritten.
|
public function getGitUrl()
|
||||||
|
{
|
||||||
|
$key = $this->getGitKey();
|
||||||
|
|
||||||
|
switch($this->getType() . '.' . (!empty($key) ? 'ssh' : 'http'))
|
||||||
|
{
|
||||||
|
case 'github.ssh':
|
||||||
|
return 'git@github.com:' . $this->getReference() . '.git';
|
||||||
|
|
||||||
|
case 'github.http':
|
||||||
|
return 'https://github.com/' . $this->getReference() . '.git';
|
||||||
|
|
||||||
|
case 'bitbucket.ssh':
|
||||||
|
return 'git@bitbucket.org:' . $this->getReference() . '.git';
|
||||||
|
|
||||||
|
case 'bitbucket.http':
|
||||||
|
return 'https://bitbucket.org/' . $this->getReference() . '.git';
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ class Composer implements \PHPCI\Plugin
|
||||||
public function __construct(\PHPCI\Builder $phpci, array $options = array())
|
public function __construct(\PHPCI\Builder $phpci, array $options = array())
|
||||||
{
|
{
|
||||||
$this->phpci = $phpci;
|
$this->phpci = $phpci;
|
||||||
$this->directory = isset($options['directory']) ? $options['directory'] : $phpci->buildPath;
|
$this->directory = isset($options['directory']) ? $phpci->buildPath . '/' . $options['directory'] : $phpci->buildPath;
|
||||||
$this->action = isset($options['action']) ? $options['action'] : 'update';
|
$this->action = isset($options['action']) ? $options['action'] : 'update';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
27
PHPCI/Plugin/Mysql.php
Normal file
27
PHPCI/Plugin/Mysql.php
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PHPCI\Plugin;
|
||||||
|
|
||||||
|
class Mysql implements \PHPCI\Plugin
|
||||||
|
{
|
||||||
|
protected $phpci;
|
||||||
|
protected $queries = array();
|
||||||
|
|
||||||
|
public function __construct(\PHPCI\Builder $phpci, array $options = array())
|
||||||
|
{
|
||||||
|
$this->phpci = $phpci;
|
||||||
|
$this->queries = $options;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function execute()
|
||||||
|
{
|
||||||
|
$rtn = true;
|
||||||
|
|
||||||
|
foreach($this->queries as $query)
|
||||||
|
{
|
||||||
|
$rtn = !$this->phpci->executeCommand('mysql -uroot -e "'.$query.'"') ? false : $rtn;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $rtn;
|
||||||
|
}
|
||||||
|
}
|
135
PHPCI/View/Build.phtml
Normal file
135
PHPCI/View/Build.phtml
Normal file
|
@ -0,0 +1,135 @@
|
||||||
|
<div id="title">
|
||||||
|
<h1 style="display: inline-block">Build #<?= $build->getId(); ?></h1>
|
||||||
|
<h3 style="margin-left: 40px; display: inline-block">Branch: <?= $build->getBranch(); ?> - <?= $build->getCommitId() == 'Manual' ? 'Manual Build' : 'Commit: ' . $build->getCommitId(); ?></h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="span3">
|
||||||
|
<div class="well" style="padding: 8px 0">
|
||||||
|
<ul class="nav nav-list">
|
||||||
|
<li><a href="/"><i class="icon-home"></i> Dashboard</a></li>
|
||||||
|
<li><a href="/project/view/<?= $build->getProject()->getId(); ?>"><i class="icon-folder-open"></i> <?= $build->getProject()->getTitle(); ?></a></li>
|
||||||
|
<li class="divider"></li>
|
||||||
|
<li class="nav-header">Options</li>
|
||||||
|
<li><a href="/build/rebuild/<?= $build->getId(); ?>"><i class="icon-cog"></i> Rebuild</a></li>
|
||||||
|
<li><a href="javascript:confirmDelete('/build/delete/<?= $build->getId(); ?>')"><i class="icon-trash"></i> Delete Build</a></li>
|
||||||
|
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="span9">
|
||||||
|
<div id="status"></div>
|
||||||
|
|
||||||
|
<table class="table table-striped table-bordered">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th style="width: 33.3%">Build Created</th>
|
||||||
|
<th style="width: 33.3%">Build Started</th>
|
||||||
|
<th style="width: 33.3%">Build Finished</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td id="created"></td>
|
||||||
|
<td id="started"></td>
|
||||||
|
<td id="finished"></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<table class="table table-striped table-bordered">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Build Log</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td><pre style="height: 300px; overflow-y: auto;" id="log"></pre></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php if($build->getStatus() == 0 || $build->getStatus() == 1 || true): ?>
|
||||||
|
<script>
|
||||||
|
setInterval(function()
|
||||||
|
{
|
||||||
|
$.getJSON('/build/data/<?= $build->getId(); ?>', updateBuildView);
|
||||||
|
}, 10000);
|
||||||
|
</script>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
window.initial = <?= $data; ?>;
|
||||||
|
|
||||||
|
function updateBuildView(data)
|
||||||
|
{
|
||||||
|
console.log(data);
|
||||||
|
$('#status').attr('class', 'alert');
|
||||||
|
|
||||||
|
var cls;
|
||||||
|
var msg;
|
||||||
|
|
||||||
|
switch(data.status)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
cls = 'alert-info';
|
||||||
|
msg = 'This build has not yet started.';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
cls = 'alert-warning';
|
||||||
|
msg = 'This build is in progress.';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
cls = 'alert-success';
|
||||||
|
msg = 'This build was successful!';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
cls = 'alert-error';
|
||||||
|
msg = 'This build has failed.';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$('#status').addClass(cls).text(msg);
|
||||||
|
|
||||||
|
if(data.created)
|
||||||
|
{
|
||||||
|
$('#created').text(data.created);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$('#created').text('Not created yet.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if(data.started)
|
||||||
|
{
|
||||||
|
$('#started').text(data.started);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$('#started').text('Not started yet.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if(data.finished)
|
||||||
|
{
|
||||||
|
$('#finished').text(data.finished);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$('#finished').text('Not finished yet.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$('#log').html(data.log);
|
||||||
|
}
|
||||||
|
|
||||||
|
$(document).ready(function()
|
||||||
|
{
|
||||||
|
updateBuildView(window.initial);
|
||||||
|
});
|
||||||
|
</script>
|
51
PHPCI/View/BuildsTable.phtml
Normal file
51
PHPCI/View/BuildsTable.phtml
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
|
||||||
|
<?php if(empty($builds) || !count($builds)): ?>
|
||||||
|
<tr class="">
|
||||||
|
<td colspan="6">No builds yet.</td>
|
||||||
|
</tr>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<?php foreach($builds as $build): ?>
|
||||||
|
<?php
|
||||||
|
switch($build->getStatus())
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
$cls = 'info';
|
||||||
|
$status = 'Pending';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
$cls = 'warning';
|
||||||
|
$status = 'Running';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
$cls = 'success';
|
||||||
|
$status = 'Success';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
$cls = 'error';
|
||||||
|
$status = 'Failed';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<tr class="<?= $cls; ?>">
|
||||||
|
<td><a href="/build/view/<?= $build->getId(); ?>">#<?= str_pad($build->getId(), 6, '0', STR_PAD_LEFT); ?></a></td>
|
||||||
|
<td><a href="/project/view/<?= $build->getProjectId(); ?>"><?= $build->getProject()->getTitle(); ?></a></td>
|
||||||
|
<td><a href="<?= $build->getCommitLink(); ?>"><?= $build->getCommitId(); ?></a></td>
|
||||||
|
<td><a href="<?= $build->getBranchLink(); ?>"><?= $build->getBranch(); ?></a></td>
|
||||||
|
<td><?= $status; ?></td>
|
||||||
|
<td>
|
||||||
|
<div class="btn-group">
|
||||||
|
<a class="btn" href="/build/view/<?= $build->getId(); ?>">View</a>
|
||||||
|
<button class="btn dropdown-toggle" data-toggle="dropdown">
|
||||||
|
<span class="caret"></span>
|
||||||
|
</button>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="javascript:confirmDelete('/build/delete/<?= $build->getId(); ?>');">Delete Build</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<?php endforeach; ?>
|
|
@ -1,27 +1,42 @@
|
||||||
|
<div id="title">
|
||||||
|
<h1 style="display: inline-block">Dashboard</h1>
|
||||||
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="span3">
|
<div class="span3">
|
||||||
<ul>
|
<div class="well" style="padding: 8px 0">
|
||||||
|
<ul class="nav nav-list">
|
||||||
|
<li><a href="/"><i class="icon-home"></i> Dashboard</a></li>
|
||||||
|
<li class="divider"></li>
|
||||||
|
<li class="nav-header">Projects</li>
|
||||||
|
|
||||||
<?php foreach($projects as $project): ?>
|
<?php foreach($projects as $project): ?>
|
||||||
<li><a href="/project/view/<?= $project->getId(); ?>"><?= $project->getTitle(); ?></a></li>
|
<li><a href="/project/view/<?= $project->getId(); ?>"><i class="icon-folder-open"></i> <?= $project->getTitle(); ?></a></li>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<div class="span9">
|
<div class="span9">
|
||||||
<table width="100%" class="table-striped table-bordered">
|
<table class="table table-striped table-bordered">
|
||||||
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
<th>ID</th>
|
||||||
<th>Project</th>
|
<th>Project</th>
|
||||||
<th>Commit</th>
|
<th>Commit</th>
|
||||||
<th>Branch</th>
|
<th>Branch</th>
|
||||||
<th>Status</th>
|
<th>Status</th>
|
||||||
|
<th style="width: 1%"></th>
|
||||||
</tr>
|
</tr>
|
||||||
<?php foreach($builds as $build): ?>
|
</thead>
|
||||||
<tr>
|
<tbody id="latest-builds">
|
||||||
<td><?= $build->getProject()->getTitle(); ?></th>
|
<?= $builds; ?>
|
||||||
<td><?= $build->getCommitId(); ?></th>
|
</tbody>
|
||||||
<td><?= $build->getBranch(); ?></th>
|
|
||||||
<td><?= $build->getStatus(); ?></th>
|
|
||||||
</tr>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
setInterval(function()
|
||||||
|
{
|
||||||
|
$('#latest-builds').load('/index/latest');
|
||||||
|
}, 10000);
|
||||||
|
</script>
|
|
@ -1,10 +1,13 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>PHPCI</title>
|
<title>PHPCI</title>
|
||||||
|
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
|
||||||
|
<link href='http://fonts.googleapis.com/css?family=Roboto:400,100,300,500,700,900,300italic' rel='stylesheet' type='text/css'>
|
||||||
<link rel="stylesheet" type="text/css" href="/assets/css/bootstrap.min.css">
|
<link rel="stylesheet" type="text/css" href="/assets/css/bootstrap.min.css">
|
||||||
<link rel="stylesheet" type="text/css" href="/assets/css/bootstrap-responsive.min.css">
|
|
||||||
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
|
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
|
||||||
<script src="/assets/js/bootstrap.min.js"></script>
|
<script src="/assets/js/bootstrap.min.js"></script>
|
||||||
|
|
||||||
|
@ -12,6 +15,9 @@
|
||||||
body
|
body
|
||||||
{
|
{
|
||||||
background: #246;
|
background: #246;
|
||||||
|
font-family: Roboto, Arial, Sans-Serif;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 300;
|
||||||
padding-top: 70px;
|
padding-top: 70px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,13 +27,58 @@
|
||||||
border: 10px solid #369;
|
border: 10px solid #369;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.widget-title, .modal-header, .table th, div.dataTables_wrapper .ui-widget-header, .ui-dialog .ui-dialog-titlebar {
|
||||||
|
background-color: #efefef;
|
||||||
|
background-image: -webkit-gradient(linear, 0 0%, 0 100%, from(#fdfdfd), to(#eaeaea));
|
||||||
|
background-image: -webkit-linear-gradient(top, #fdfdfd 0%, #eaeaea 100%);
|
||||||
|
background-image: -moz-linear-gradient(top, #fdfdfd 0%, #eaeaea 100%);
|
||||||
|
background-image: -ms-linear-gradient(top, #fdfdfd 0%, #eaeaea 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #fdfdfd 0%, #eaeaea 100%);
|
||||||
|
background-image: -linear-gradient(top, #fdfdfd 0%, #eaeaea 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#fdfdfd', endColorstr='#eaeaea',GradientType=0 ); /* IE6-9 */
|
||||||
|
border-bottom: 1px solid #CDCDCD;
|
||||||
|
}
|
||||||
|
|
||||||
|
#title
|
||||||
|
{
|
||||||
|
background: #f8f8f8;
|
||||||
|
border-bottom: 1px solid #ccc;
|
||||||
|
margin: -10px -10px 15px -10px;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#title h1
|
||||||
|
{
|
||||||
|
font-size: 2em;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
function confirmDelete(url)
|
||||||
|
{
|
||||||
|
if(confirm('Are you sure you want to delete this?'))
|
||||||
|
{
|
||||||
|
window.location.href = url;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="navbar navbar-fixed-top">
|
<div class="navbar navbar-fixed-top">
|
||||||
<div class="navbar-inner">
|
<div class="navbar-inner">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<a class="brand" href="/">PHPCI</a>
|
<a class="brand" href="/">PHPCI <span class="badge badge-important" style="position: relative; top: -3px; margin-left: 10px">1.0 Alpha</span></a>
|
||||||
|
|
||||||
|
<a class="pull-right btn" href="/project/add">Add Project</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
85
PHPCI/View/Project.phtml
Normal file
85
PHPCI/View/Project.phtml
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
<div id="title">
|
||||||
|
<h1>Project: <?= $project->getTitle(); ?></h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="span3">
|
||||||
|
<div class="well" style="padding: 8px 0">
|
||||||
|
<ul class="nav nav-list">
|
||||||
|
<li><a href="/"><i class="icon-home"></i> Dashboard</a></li>
|
||||||
|
<li><a href="/project/view/<?= $project->getId(); ?>"><i class="icon-folder-open"></i> <?= $project->getTitle(); ?></a></li>
|
||||||
|
<li class="divider"></li>
|
||||||
|
<li class="nav-header">Options</li>
|
||||||
|
<li><a href="/project/edit/<?= $project->getId(); ?>"><i class="icon-edit"></i> Edit Project</a></li>
|
||||||
|
<li><a href="/project/build/<?= $project->getId(); ?>"><i class="icon-cog"></i> Build Now</a></li>
|
||||||
|
<li><a href="javascript:confirmDelete('/project/delete/<?= $project->getId(); ?>')"><i class="icon-trash"></i> Delete Project</a></li>
|
||||||
|
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
<p class="alert alert-info">To automatically build this project when new commits are pushed, add the URL below
|
||||||
|
|
||||||
|
<?php
|
||||||
|
switch($project->getType())
|
||||||
|
{
|
||||||
|
case 'github':
|
||||||
|
$url = (empty($_SERVER['HTTPS']) ? 'http' : 'https') . '://' . $_SERVER['HTTP_HOST'] . '/github/webhook/' . $project->getId();
|
||||||
|
print ' as a "WebHook URL" in the <a href="https://github.com/' . $project->getReference() . '/settings/hooks">Service Hooks</a> section of your Github repository.<br><br><strong style="word-wrap: break-word;">' . $url . '</strong>';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'bitbucket':
|
||||||
|
$url = (empty($_SERVER['HTTPS']) ? 'http' : 'https') . '://' . $_SERVER['HTTP_HOST'] . '/bitbucket/webhook/' . $project->getId();
|
||||||
|
print ' as a "POST" service in the <a href="https://bitbucket.org/' . $project->getReference() . '/admin/services">Services</a> section of your Bitbucket repository.<br><br><strong style="word-wrap: break-word;">' . $url . '</strong>';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="span9">
|
||||||
|
<table class="table table-striped table-bordered">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>ID</th>
|
||||||
|
<th>Project</th>
|
||||||
|
<th>Commit</th>
|
||||||
|
<th>Branch</th>
|
||||||
|
<th>Status</th>
|
||||||
|
<th style="width: 1%"></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody id="latest-builds">
|
||||||
|
<?= $builds; ?>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
|
||||||
|
print '<div class="pagination"><ul>';
|
||||||
|
$pages = ceil($total / 10);
|
||||||
|
$pages = $pages == 0 ? 1 : $pages;
|
||||||
|
|
||||||
|
print '<li class="'.($page == 1 ? 'disabled' : '').'"><a href="/project/view/'.$project->getId().'?p='.($page == 1 ? '1' : $page - 1).'">«</a></li>';
|
||||||
|
|
||||||
|
for($i = 1; $i <= $pages; $i++)
|
||||||
|
{
|
||||||
|
print '<li><a href="/project/view/' . $project->getId() . '?p=' . $i . '">' . $i . '</a></li>';
|
||||||
|
}
|
||||||
|
|
||||||
|
print '<li class="'.($page == $pages ? 'disabled' : '').'"><a href="/project/view/'.$project->getId().'?p='.($page == $pages ? $pages : $page + 1).'">»</a></li>';
|
||||||
|
|
||||||
|
print '</ul></div>';
|
||||||
|
|
||||||
|
?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php if($page == 1): ?>
|
||||||
|
<script>
|
||||||
|
setInterval(function()
|
||||||
|
{
|
||||||
|
$('#latest-builds').load('/project/builds/<?= $project->getId(); ?>');
|
||||||
|
}, 10000);
|
||||||
|
</script>
|
||||||
|
<?php endif; ?>
|
22
PHPCI/View/ProjectForm.phtml
Normal file
22
PHPCI/View/ProjectForm.phtml
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
<div id="title">
|
||||||
|
<h1><?= $type == 'add' ? 'Add Project' : 'Edit Project' ?></h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="span4">
|
||||||
|
<div class="well" style="">
|
||||||
|
<?php if(!is_null($key)): ?>
|
||||||
|
<p>To make it easier to get started, we've generated a public / private key pair for you to use for this project. To use it, just add the following public key to the "deploy keys" section of your repository settings on Github / Bitbucket.</p>
|
||||||
|
|
||||||
|
<textarea style="width: 90%; height: 150px;"><?= $key ?></textarea>
|
||||||
|
<?php elseif($type == 'add'): ?>
|
||||||
|
<p>Fill in the form to the right to add your new project.</p>
|
||||||
|
<?php else: ?>
|
||||||
|
<p>Edit your project details using the form to the right.</p>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="span8">
|
||||||
|
<?= $form; ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
BIN
assets/.DS_Store
vendored
BIN
assets/.DS_Store
vendored
Binary file not shown.
1109
assets/css/bootstrap-responsive.css
vendored
1109
assets/css/bootstrap-responsive.css
vendored
File diff suppressed because it is too large
Load diff
9
assets/css/bootstrap-responsive.min.css
vendored
9
assets/css/bootstrap-responsive.min.css
vendored
File diff suppressed because one or more lines are too long
6158
assets/css/bootstrap.css
vendored
6158
assets/css/bootstrap.css
vendored
File diff suppressed because it is too large
Load diff
836
assets/css/bootstrap.min.css
vendored
Normal file → Executable file
836
assets/css/bootstrap.min.css
vendored
Normal file → Executable file
File diff suppressed because one or more lines are too long
2902
assets/js/bootstrap.js
vendored
Normal file → Executable file
2902
assets/js/bootstrap.js
vendored
Normal file → Executable file
File diff suppressed because it is too large
Load diff
5
assets/js/bootstrap.min.js
vendored
Normal file → Executable file
5
assets/js/bootstrap.min.js
vendored
Normal file → Executable file
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue