Merge branch 'master' into phplint-output-block
This commit is contained in:
commit
a1d240faa4
|
@ -215,15 +215,6 @@ class Builder implements LoggerAwareInterface
|
|||
$this->pluginExecutor->executePlugins($this->config, 'failure');
|
||||
$this->buildLogger->logFailure(Lang::get('build_failed'));
|
||||
}
|
||||
|
||||
// Clean up:
|
||||
$this->buildLogger->log(Lang::get('removing_build'));
|
||||
|
||||
$cmd = 'rm -Rf "%s"';
|
||||
if (IS_WIN) {
|
||||
$cmd = 'rmdir /S /Q "%s"';
|
||||
}
|
||||
$this->executeCommand($cmd, rtrim($this->buildPath, '/'));
|
||||
} catch (\Exception $ex) {
|
||||
$this->build->setStatus(Build::STATUS_FAILED);
|
||||
$this->buildLogger->logFailure(Lang::get('exception') . $ex->getMessage());
|
||||
|
@ -233,6 +224,11 @@ class Builder implements LoggerAwareInterface
|
|||
// Update the build in the database, ping any external services, etc.
|
||||
$this->build->sendStatusPostback();
|
||||
$this->build->setFinished(new \DateTime());
|
||||
|
||||
// Clean up:
|
||||
$this->buildLogger->log(Lang::get('removing_build'));
|
||||
$this->build->removeBuildDirectory();
|
||||
|
||||
$this->store->save($this->build);
|
||||
}
|
||||
|
||||
|
@ -263,12 +259,14 @@ class Builder implements LoggerAwareInterface
|
|||
|
||||
/**
|
||||
* Find a binary required by a plugin.
|
||||
* @param $binary
|
||||
* @param string $binary
|
||||
* @param bool $quiet
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
public function findBinary($binary)
|
||||
public function findBinary($binary, $quiet = false)
|
||||
{
|
||||
return $this->commandExecutor->findBinary($binary, $this->buildPath);
|
||||
return $this->commandExecutor->findBinary($binary, $quiet = false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -287,7 +285,7 @@ class Builder implements LoggerAwareInterface
|
|||
*/
|
||||
protected function setupBuild()
|
||||
{
|
||||
$this->buildPath = PHPCI_DIR . 'PHPCI/build/' . $this->build->getId() . '/';
|
||||
$this->buildPath = $this->build->getBuildPath() . '/';
|
||||
$this->build->currentBuildPath = $this->buildPath;
|
||||
|
||||
$this->interpolator->setupInterpolationVars(
|
||||
|
|
85
PHPCI/Command/CreateBuildCommand.php
Normal file
85
PHPCI/Command/CreateBuildCommand.php
Normal file
|
@ -0,0 +1,85 @@
|
|||
<?php
|
||||
/**
|
||||
* 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/
|
||||
*/
|
||||
|
||||
namespace PHPCI\Command;
|
||||
|
||||
use PHPCI\Helper\Lang;
|
||||
use PHPCI\Service\BuildService;
|
||||
use PHPCI\Store\ProjectStore;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
* Create build command - creates a build for a project
|
||||
* @author Jérémy DECOOL (@jdecool)
|
||||
* @package PHPCI
|
||||
* @subpackage Console
|
||||
*/
|
||||
class CreateBuildCommand extends Command
|
||||
{
|
||||
/**
|
||||
* @var ProjectStore
|
||||
*/
|
||||
protected $projectStore;
|
||||
|
||||
/**
|
||||
* @var BuildService
|
||||
*/
|
||||
protected $buildService;
|
||||
|
||||
/**
|
||||
* @param ProjectStore $projectStore
|
||||
*/
|
||||
public function __construct(ProjectStore $projectStore, BuildService $buildService)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->projectStore = $projectStore;
|
||||
$this->buildService = $buildService;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
->setName('phpci:create-build')
|
||||
->setDescription(Lang::get('create_build_project'))
|
||||
->addArgument('projectId', InputArgument::REQUIRED, Lang::get('project_id_argument'))
|
||||
->addOption('commit', null, InputOption::VALUE_OPTIONAL, Lang::get('commit_id_option'))
|
||||
->addOption('branch', null, InputOption::VALUE_OPTIONAL, Lang::get('branch_name_option'));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$projectId = $input->getArgument('projectId');
|
||||
$commitId = $input->getOption('commit');
|
||||
$branch = $input->getOption('branch');
|
||||
|
||||
$project = $this->projectStore->getById($projectId);
|
||||
if (empty($project)) {
|
||||
throw new \InvalidArgumentException('Project does not exist: ' . $projectId);
|
||||
}
|
||||
|
||||
try {
|
||||
$this->buildService->createBuild($project, $commitId, $branch);
|
||||
$output->writeln(Lang::get('build_created'));
|
||||
} catch (\Exception $e) {
|
||||
$output->writeln(sprintf('<error>%s</error>', Lang::get('failed')));
|
||||
$output->writeln(sprintf('<error>%s</error>', $e->getMessage()));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* PHPCI - Continuous Integration for PHP
|
||||
*
|
||||
|
@ -10,28 +11,48 @@
|
|||
namespace PHPCI\Command;
|
||||
|
||||
use Monolog\Logger;
|
||||
use PHPCI\ProcessControl\Factory;
|
||||
use PHPCI\ProcessControl\ProcessControlInterface;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
* Daemon that loops and call the run-command.
|
||||
* @author Gabriel Baker <gabriel.baker@autonomicpilot.co.uk>
|
||||
* @package PHPCI
|
||||
* @subpackage Console
|
||||
*/
|
||||
* Daemon that loops and call the run-command.
|
||||
* @author Gabriel Baker <gabriel.baker@autonomicpilot.co.uk>
|
||||
* @package PHPCI
|
||||
* @subpackage Console
|
||||
*/
|
||||
class DaemonCommand extends Command
|
||||
{
|
||||
|
||||
/**
|
||||
* @var \Monolog\Logger
|
||||
* @var Logger
|
||||
*/
|
||||
protected $logger;
|
||||
|
||||
public function __construct(Logger $logger, $name = null)
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $pidFilePath;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $logFilePath;
|
||||
|
||||
/**
|
||||
* @var ProcessControlInterface
|
||||
*/
|
||||
protected $processControl;
|
||||
|
||||
public function __construct(Logger $logger, ProcessControlInterface $processControl = null, $name = null)
|
||||
{
|
||||
parent::__construct($name);
|
||||
$this->logger = $logger;
|
||||
$this->processControl = $processControl ?: Factory::getInstance();
|
||||
}
|
||||
|
||||
protected function configure()
|
||||
|
@ -40,17 +61,30 @@ class DaemonCommand extends Command
|
|||
->setName('phpci:daemon')
|
||||
->setDescription('Initiates the daemon to run commands.')
|
||||
->addArgument(
|
||||
'state',
|
||||
InputArgument::REQUIRED,
|
||||
'start|stop|status'
|
||||
);
|
||||
'state', InputArgument::REQUIRED, 'start|stop|status'
|
||||
)
|
||||
->addOption(
|
||||
'pid-file', 'p', InputOption::VALUE_REQUIRED,
|
||||
'Path of the PID file',
|
||||
implode(DIRECTORY_SEPARATOR,
|
||||
array(PHPCI_DIR, 'daemon', 'daemon.pid'))
|
||||
)
|
||||
->addOption(
|
||||
'log-file', 'l', InputOption::VALUE_REQUIRED,
|
||||
'Path of the log file',
|
||||
implode(DIRECTORY_SEPARATOR,
|
||||
array(PHPCI_DIR, 'daemon', 'daemon.log'))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loops through running.
|
||||
*/
|
||||
* Loops through running.
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$this->pidFilePath = $input->getOption('pid-file');
|
||||
$this->logFilePath = $input->getOption('log-file');
|
||||
|
||||
$state = $input->getArgument('state');
|
||||
|
||||
switch ($state) {
|
||||
|
@ -61,64 +95,108 @@ class DaemonCommand extends Command
|
|||
$this->stopDaemon();
|
||||
break;
|
||||
case 'status':
|
||||
$this->statusDaemon();
|
||||
$this->statusDaemon($output);
|
||||
break;
|
||||
default:
|
||||
echo "Not a valid choice, please use start stop or status";
|
||||
$this->output->writeln("<error>Not a valid choice, please use start, stop or status</error>");
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected function startDaemon()
|
||||
{
|
||||
|
||||
if (file_exists(PHPCI_DIR.'/daemon/daemon.pid')) {
|
||||
echo "Already started\n";
|
||||
$this->logger->warning("Daemon already started");
|
||||
$pid = $this->getRunningPid();
|
||||
if ($pid) {
|
||||
$this->logger->notice("Daemon already started", array('pid' => $pid));
|
||||
return "alreadystarted";
|
||||
}
|
||||
|
||||
$logfile = PHPCI_DIR."/daemon/daemon.log";
|
||||
$this->logger->info("Trying to start the daemon");
|
||||
|
||||
$cmd = "nohup %s/daemonise phpci:daemonise > %s 2>&1 &";
|
||||
$command = sprintf($cmd, PHPCI_DIR, $logfile);
|
||||
$this->logger->info("Daemon started");
|
||||
exec($command);
|
||||
$command = sprintf($cmd, PHPCI_DIR, $this->logFilePath);
|
||||
$output = $exitCode = null;
|
||||
exec($command, $output, $exitCode);
|
||||
|
||||
if ($exitCode !== 0) {
|
||||
$this->logger->error(sprintf("daemonise exited with status %d", $exitCode));
|
||||
return "notstarted";
|
||||
}
|
||||
|
||||
for ($i = 0; !($pid = $this->getRunningPid()) && $i < 5; $i++) {
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
if (!$pid) {
|
||||
$this->logger->error("Could not start the daemon");
|
||||
return "notstarted";
|
||||
}
|
||||
|
||||
$this->logger->notice("Daemon started", array('pid' => $pid));
|
||||
return "started";
|
||||
}
|
||||
|
||||
protected function stopDaemon()
|
||||
{
|
||||
|
||||
if (!file_exists(PHPCI_DIR.'/daemon/daemon.pid')) {
|
||||
echo "Not started\n";
|
||||
$this->logger->warning("Can't stop daemon as not started");
|
||||
$pid = $this->getRunningPid();
|
||||
if (!$pid) {
|
||||
$this->logger->notice("Cannot stop the daemon as it is not started");
|
||||
return "notstarted";
|
||||
}
|
||||
|
||||
$cmd = "kill $(cat %s/daemon/daemon.pid)";
|
||||
$command = sprintf($cmd, PHPCI_DIR);
|
||||
exec($command);
|
||||
$this->logger->info("Daemon stopped");
|
||||
unlink(PHPCI_DIR.'/daemon/daemon.pid');
|
||||
}
|
||||
$this->logger->info("Trying to terminate the daemon", array('pid' => $pid));
|
||||
$this->processControl->kill($pid);
|
||||
|
||||
protected function statusDaemon()
|
||||
{
|
||||
|
||||
if (!file_exists(PHPCI_DIR.'/daemon/daemon.pid')) {
|
||||
echo "Not running\n";
|
||||
return "notrunning";
|
||||
for ($i = 0; ($pid = $this->getRunningPid()) && $i < 5; $i++) {
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
$pid = trim(file_get_contents(PHPCI_DIR.'/daemon/daemon.pid'));
|
||||
$pidcheck = sprintf("/proc/%s", $pid);
|
||||
if (is_dir($pidcheck)) {
|
||||
echo "Running\n";
|
||||
if ($pid) {
|
||||
$this->logger->warning("The daemon is resiting, trying to kill it", array('pid' => $pid));
|
||||
$this->processControl->kill($pid, true);
|
||||
|
||||
for ($i = 0; ($pid = $this->getRunningPid()) && $i < 5; $i++) {
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!$pid) {
|
||||
$this->logger->notice("Daemon stopped");
|
||||
return "stopped";
|
||||
}
|
||||
|
||||
$this->logger->error("Could not stop the daemon");
|
||||
}
|
||||
|
||||
protected function statusDaemon(OutputInterface $output)
|
||||
{
|
||||
$pid = $this->getRunningPid();
|
||||
if ($pid) {
|
||||
$output->writeln(sprintf('The daemon is running, PID: %d', $pid));
|
||||
return "running";
|
||||
}
|
||||
|
||||
unlink(PHPCI_DIR.'/daemon/daemon.pid');
|
||||
echo "Not running\n";
|
||||
$output->writeln('The daemon is not running');
|
||||
return "notrunning";
|
||||
}
|
||||
|
||||
/** Check if there is a running daemon
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
protected function getRunningPid()
|
||||
{
|
||||
if (!file_exists($this->pidFilePath)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$pid = intval(trim(file_get_contents($this->pidFilePath)));
|
||||
|
||||
if($this->processControl->isRunning($pid, true)) {
|
||||
return $pid;
|
||||
}
|
||||
|
||||
// Not found, remove the stale PID file
|
||||
unlink($this->pidFilePath);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -323,7 +323,9 @@ class InstallCommand extends Command
|
|||
{
|
||||
$output->write(Lang::get('setting_up_db'));
|
||||
|
||||
shell_exec(PHPCI_DIR . 'vendor/bin/phinx migrate -c "' . PHPCI_DIR . 'phinx.php"');
|
||||
$phinxBinary = escapeshellarg(PHPCI_DIR . 'vendor/bin/phinx');
|
||||
$phinxScript = escapeshellarg(PHPCI_DIR . 'phinx.php');
|
||||
shell_exec($phinxBinary . ' migrate -c ' . $phinxScript);
|
||||
|
||||
$output->writeln('<info>'.Lang::get('ok').'</info>');
|
||||
}
|
||||
|
|
|
@ -75,7 +75,8 @@ class RebuildCommand extends Command
|
|||
$store = Factory::getStore('Build');
|
||||
$service = new BuildService($store);
|
||||
|
||||
$lastBuild = array_shift($store->getLatestBuilds(null, 1));
|
||||
$builds = $store->getLatestBuilds(null, 1);
|
||||
$lastBuild = array_shift($builds);
|
||||
$service->createDuplicateBuild($lastBuild);
|
||||
|
||||
$runner->run(new ArgvInput(array()), $output);
|
||||
|
|
|
@ -166,7 +166,7 @@ class RunCommand extends Command
|
|||
$build->setStatus(Build::STATUS_FAILED);
|
||||
$build->setFinished(new \DateTime());
|
||||
$store->save($build);
|
||||
$this->removeBuildDirectory($build);
|
||||
$build->removeBuildDirectory();
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -175,19 +175,4 @@ class RunCommand extends Command
|
|||
|
||||
return $rtn;
|
||||
}
|
||||
|
||||
protected function removeBuildDirectory($build)
|
||||
{
|
||||
$buildPath = PHPCI_DIR . 'PHPCI/build/' . $build->getId() . '/';
|
||||
|
||||
if (is_dir($buildPath)) {
|
||||
$cmd = 'rm -Rf "%s"';
|
||||
|
||||
if (IS_WIN) {
|
||||
$cmd = 'rmdir /S /Q "%s"';
|
||||
}
|
||||
|
||||
shell_exec($cmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ use b8;
|
|||
use b8\Exception\HttpException\NotFoundException;
|
||||
use b8\Http\Response\JsonResponse;
|
||||
use PHPCI\BuildFactory;
|
||||
use PHPCI\Helper\AnsiConverter;
|
||||
use PHPCI\Helper\Lang;
|
||||
use PHPCI\Model\Build;
|
||||
use PHPCI\Model\Project;
|
||||
|
@ -198,11 +199,7 @@ class BuildController extends \PHPCI\Controller
|
|||
*/
|
||||
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;
|
||||
return AnsiConverter::convert($log);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -15,6 +15,7 @@ use b8\Store;
|
|||
use PHPCI\BuildFactory;
|
||||
use PHPCI\Model\Project;
|
||||
use PHPCI\Model\Build;
|
||||
use PHPCI\Service\BuildStatusService;
|
||||
|
||||
/**
|
||||
* Build Status Controller - Allows external access to build status information / images.
|
||||
|
@ -24,10 +25,9 @@ use PHPCI\Model\Build;
|
|||
*/
|
||||
class BuildStatusController extends \PHPCI\Controller
|
||||
{
|
||||
/**
|
||||
* @var \PHPCI\Store\ProjectStore
|
||||
*/
|
||||
/* @var \PHPCI\Store\ProjectStore */
|
||||
protected $projectStore;
|
||||
/* @var \PHPCI\Store\BuildStore */
|
||||
protected $buildStore;
|
||||
|
||||
/**
|
||||
|
@ -70,11 +70,70 @@ class BuildStatusController extends \PHPCI\Controller
|
|||
return $status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays projects information in ccmenu format
|
||||
*
|
||||
* @param $projectId
|
||||
* @return bool
|
||||
* @throws \Exception
|
||||
* @throws b8\Exception\HttpException
|
||||
*/
|
||||
public function ccxml($projectId)
|
||||
{
|
||||
/* @var Project $project */
|
||||
$project = $this->projectStore->getById($projectId);
|
||||
$xml = new \SimpleXMLElement('<Projects/>');
|
||||
|
||||
if (!$project instanceof Project || !$project->getAllowPublicStatus()) {
|
||||
return $this->renderXml($xml);
|
||||
}
|
||||
|
||||
try {
|
||||
$branchList = $this->buildStore->getBuildBranches($projectId);
|
||||
|
||||
if (!$branchList) {
|
||||
$branchList = array($project->getBranch());
|
||||
}
|
||||
|
||||
foreach ($branchList as $branch) {
|
||||
$buildStatusService = new BuildStatusService($branch, $project, $project->getLatestBuild($branch));
|
||||
if ($attributes = $buildStatusService->toArray()) {
|
||||
$projectXml = $xml->addChild('Project');
|
||||
foreach ($attributes as $attributeKey => $attributeValue) {
|
||||
$projectXml->addAttribute($attributeKey, $attributeValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch (\Exception $e) {
|
||||
$xml = new \SimpleXMLElement('<projects/>');
|
||||
}
|
||||
|
||||
return $this->renderXml($xml);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \SimpleXMLElement $xml
|
||||
* @return bool
|
||||
*/
|
||||
protected function renderXml(\SimpleXMLElement $xml = null)
|
||||
{
|
||||
$this->response->setHeader('Content-Type', 'text/xml');
|
||||
$this->response->setContent($xml->asXML());
|
||||
$this->response->flush();
|
||||
echo $xml->asXML();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the appropriate build status image in SVG format for a given project.
|
||||
*/
|
||||
public function image($projectId)
|
||||
{
|
||||
$style = $this->getParam('style', 'plastic');
|
||||
$label = $this->getParam('label', 'build');
|
||||
|
||||
$status = $this->getStatus($projectId);
|
||||
|
||||
if (is_null($status)) {
|
||||
|
@ -84,7 +143,13 @@ class BuildStatusController extends \PHPCI\Controller
|
|||
}
|
||||
|
||||
$color = ($status == 'passing') ? 'green' : 'red';
|
||||
$image = file_get_contents('http://img.shields.io/badge/build-' . $status . '-' . $color . '.svg');
|
||||
$image = file_get_contents(sprintf(
|
||||
'http://img.shields.io/badge/%s-%s-%s.svg?style=%s',
|
||||
$label,
|
||||
$status,
|
||||
$color,
|
||||
$style
|
||||
));
|
||||
|
||||
$this->response->disableLayout();
|
||||
$this->response->setHeader('Content-Type', 'image/svg+xml');
|
||||
|
|
|
@ -98,12 +98,22 @@ class HomeController extends \PHPCI\Controller
|
|||
protected function getSummaryHtml($projects)
|
||||
{
|
||||
$summaryBuilds = array();
|
||||
$successes = array();
|
||||
$failures = array();
|
||||
$successes = array();
|
||||
$failures = array();
|
||||
$counts = array();
|
||||
|
||||
foreach ($projects['items'] as $project) {
|
||||
$summaryBuilds[$project->getId()] = $this->buildStore->getLatestBuilds($project->getId());
|
||||
|
||||
$count = $this->buildStore->getWhere(
|
||||
array('project_id' => $project->getId()),
|
||||
1,
|
||||
0,
|
||||
array(),
|
||||
array('id' => 'DESC')
|
||||
);
|
||||
$counts[$project->getId()] = $count['count'];
|
||||
|
||||
$success = $this->buildStore->getLastBuildByStatus($project->getId(), Build::STATUS_SUCCESS);
|
||||
$failure = $this->buildStore->getLastBuildByStatus($project->getId(), Build::STATUS_FAILED);
|
||||
|
||||
|
@ -112,10 +122,11 @@ class HomeController extends \PHPCI\Controller
|
|||
}
|
||||
|
||||
$summaryView = new b8\View('SummaryTable');
|
||||
$summaryView->projects = $projects['items'];
|
||||
$summaryView->builds = $summaryBuilds;
|
||||
$summaryView->projects = $projects['items'];
|
||||
$summaryView->builds = $summaryBuilds;
|
||||
$summaryView->successful = $successes;
|
||||
$summaryView->failed = $failures;
|
||||
$summaryView->failed = $failures;
|
||||
$summaryView->counts = $counts;
|
||||
|
||||
return $summaryView->render();
|
||||
}
|
||||
|
|
|
@ -86,7 +86,7 @@ class ProjectController extends PHPCI\Controller
|
|||
$this->view->builds = $builds[0];
|
||||
$this->view->total = $builds[1];
|
||||
$this->view->project = $project;
|
||||
$this->view->branch = urldecode($branch);
|
||||
$this->view->branch = urldecode($branch);
|
||||
$this->view->branches = $this->projectStore->getKnownBranches($projectId);
|
||||
$this->view->page = $page;
|
||||
$this->view->pages = $pages;
|
||||
|
|
|
@ -43,15 +43,23 @@ class SessionController extends \PHPCI\Controller
|
|||
$isLoginFailure = false;
|
||||
|
||||
if ($this->request->getMethod() == 'POST') {
|
||||
$user = $this->userStore->getByEmail($this->getParam('email'));
|
||||
|
||||
if ($user && password_verify($this->getParam('password', ''), $user->getHash())) {
|
||||
$_SESSION['phpci_user_id'] = $user->getId();
|
||||
$response = new b8\Http\Response\RedirectResponse();
|
||||
$response->setHeader('Location', $this->getLoginRedirect());
|
||||
return $response;
|
||||
} else {
|
||||
$token = $this->getParam('token');
|
||||
if ($token === null || $token !== $_SESSION['login_token']) {
|
||||
$isLoginFailure = true;
|
||||
} else {
|
||||
unset($_SESSION['login_token']);
|
||||
|
||||
$user = $this->userStore->getByLoginOrEmail($this->getParam('email'));
|
||||
|
||||
if ($user && password_verify($this->getParam('password', ''), $user->getHash())) {
|
||||
session_regenerate_id(true);
|
||||
$_SESSION['phpci_user_id'] = $user->getId();
|
||||
$response = new b8\Http\Response\RedirectResponse();
|
||||
$response->setHeader('Location', $this->getLoginRedirect());
|
||||
return $response;
|
||||
} else {
|
||||
$isLoginFailure = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -60,7 +68,7 @@ class SessionController extends \PHPCI\Controller
|
|||
$form->setAction(PHPCI_URL.'session/login');
|
||||
|
||||
$email = new b8\Form\Element\Email('email');
|
||||
$email->setLabel(Lang::get('email_address'));
|
||||
$email->setLabel(Lang::get('login'));
|
||||
$email->setRequired(true);
|
||||
$email->setContainerClass('form-group');
|
||||
$email->setClass('form-control');
|
||||
|
@ -78,9 +86,15 @@ class SessionController extends \PHPCI\Controller
|
|||
$pwd->setClass('btn-success');
|
||||
$form->addField($pwd);
|
||||
|
||||
$tokenValue = $this->generateToken();
|
||||
$_SESSION['login_token'] = $tokenValue;
|
||||
$token = new b8\Form\Element\Hidden('token');
|
||||
$token->setValue($tokenValue);
|
||||
$form->addField($token);
|
||||
|
||||
$this->view->form = $form->render();
|
||||
$this->view->failed = $isLoginFailure;
|
||||
|
||||
|
||||
return $this->view->render();
|
||||
}
|
||||
|
||||
|
@ -180,4 +194,20 @@ class SessionController extends \PHPCI\Controller
|
|||
|
||||
return $rtn;
|
||||
}
|
||||
|
||||
/** Generate a random token.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function generateToken()
|
||||
{
|
||||
if (function_exists('openssl_random_pseudo_bytes')) {
|
||||
return bin2hex(openssl_random_pseudo_bytes(16));
|
||||
}
|
||||
|
||||
return sprintf("%04x", mt_rand(0, 0xFFFF))
|
||||
. sprintf("%04x", mt_rand(0, 0xFFFF))
|
||||
. sprintf("%04x", mt_rand(0, 0xFFFF))
|
||||
. sprintf("%04x", mt_rand(0, 0xFFFF));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -329,7 +329,7 @@ class SettingsController extends Controller
|
|||
$field->setContainerClass('form-group');
|
||||
$form->addField($field);
|
||||
|
||||
$field = new Form\Element\Text('smtp_password');
|
||||
$field = new Form\Element\Password('smtp_password');
|
||||
$field->setRequired(false);
|
||||
$field->setLabel(Lang::get('smtp_password'));
|
||||
$field->setClass('form-control');
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
/**
|
||||
* PHPCI - Continuous Integration for PHP
|
||||
*
|
||||
* @copyright Copyright 2014, Block 8 Limited.
|
||||
* @copyright Copyright 2014-2015, Block 8 Limited.
|
||||
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
|
||||
* @link https://www.phptesting.org/
|
||||
*/
|
||||
|
@ -11,31 +11,37 @@ namespace PHPCI\Controller;
|
|||
|
||||
use b8;
|
||||
use b8\Store;
|
||||
use Exception;
|
||||
use PHPCI\BuildFactory;
|
||||
use PHPCI\Model\Project;
|
||||
use PHPCI\Service\BuildService;
|
||||
use PHPCI\Store\BuildStore;
|
||||
use PHPCI\Store\ProjectStore;
|
||||
|
||||
/**
|
||||
* Webhook Controller - Processes webhook pings from BitBucket, Github, Gitlab, etc.
|
||||
*
|
||||
* @author Dan Cryer <dan@block8.co.uk>
|
||||
* @author Sami Tikka <stikka@iki.fi>
|
||||
* @author Alex Russell <alex@clevercherry.com>
|
||||
* @author Guillaume Perréal <adirelle@gmail.com>
|
||||
* @package PHPCI
|
||||
* @subpackage Web
|
||||
*/
|
||||
class WebhookController extends \PHPCI\Controller
|
||||
class WebhookController extends \b8\Controller
|
||||
{
|
||||
/**
|
||||
* @var \PHPCI\Store\BuildStore
|
||||
* @var BuildStore
|
||||
*/
|
||||
protected $buildStore;
|
||||
|
||||
/**
|
||||
* @var \PHPCI\Store\ProjectStore
|
||||
* @var ProjectStore
|
||||
*/
|
||||
protected $projectStore;
|
||||
|
||||
/**
|
||||
* @var \PHPCI\Service\BuildService
|
||||
* @var BuildService
|
||||
*/
|
||||
protected $buildService;
|
||||
|
||||
|
@ -49,283 +55,311 @@ class WebhookController extends \PHPCI\Controller
|
|||
$this->buildService = new BuildService($this->buildStore);
|
||||
}
|
||||
|
||||
/** Handle the action, Ensuring to return a JsonResponse.
|
||||
*
|
||||
* @param string $action
|
||||
* @param mixed $actionParams
|
||||
*
|
||||
* @return \b8\Http\Response
|
||||
*/
|
||||
public function handleAction($action, $actionParams)
|
||||
{
|
||||
$response = new b8\Http\Response\JsonResponse();
|
||||
try {
|
||||
$data = parent::handleAction($action, $actionParams);
|
||||
if (isset($data['responseCode'])) {
|
||||
$response->setResponseCode($data['responseCode']);
|
||||
unset($data['responseCode']);
|
||||
}
|
||||
$response->setContent($data);
|
||||
} catch (Exception $ex) {
|
||||
$response->setResponseCode(500);
|
||||
$response->setContent(array('status' => 'failed', 'error' => $ex->getMessage()));
|
||||
}
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by Bitbucket POST service.
|
||||
*/
|
||||
public function bitbucket($project)
|
||||
public function bitbucket($projectId)
|
||||
{
|
||||
$response = new b8\Http\Response\JsonResponse();
|
||||
$response->setContent(array('status' => 'ok'));
|
||||
|
||||
$project = $this->fetchProject($projectId, 'bitbucket');
|
||||
$payload = json_decode($this->getParam('payload'), true);
|
||||
|
||||
$results = array();
|
||||
$status = 'failed';
|
||||
foreach ($payload['commits'] as $commit) {
|
||||
try {
|
||||
$email = $commit['raw_author'];
|
||||
$email = substr($email, 0, strpos($email, '>'));
|
||||
$email = substr($email, strpos($email, '<') + 1);
|
||||
|
||||
$this->createBuild($project, $commit['raw_node'], $commit['branch'], $email, $commit['message']);
|
||||
} catch (\Exception $ex) {
|
||||
$response->setResponseCode(500);
|
||||
$response->setContent(array('status' => 'failed', 'error' => $ex->getMessage()));
|
||||
break;
|
||||
$results[$commit['raw_node']] = $this->createBuild(
|
||||
$project,
|
||||
$commit['raw_node'],
|
||||
$commit['branch'],
|
||||
$email,
|
||||
$commit['message']
|
||||
);
|
||||
$status = 'ok';
|
||||
} catch (Exception $ex) {
|
||||
$results[$commit['raw_node']] = array('status' => 'failed', 'error' => $ex->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
return $response;
|
||||
return array('status' => $status, 'commits' => $results);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by POSTing to /webhook/git/<project_id>?branch=<branch>&commit=<commit>
|
||||
*
|
||||
* @param string $project
|
||||
* @param string $projectId
|
||||
*/
|
||||
public function git($project)
|
||||
public function git($projectId)
|
||||
{
|
||||
$response = new b8\Http\Response\JsonResponse();
|
||||
$response->setContent(array('status' => 'ok'));
|
||||
|
||||
$branch = $this->getParam('branch');
|
||||
$project = $this->fetchProject($projectId, array('local', 'remote'));
|
||||
$branch = $this->getParam('branch', $project->getBranch());
|
||||
$commit = $this->getParam('commit');
|
||||
$commitMessage = $this->getParam('message');
|
||||
$committer = $this->getParam('committer');
|
||||
|
||||
try {
|
||||
if (empty($branch)) {
|
||||
$branch = 'master';
|
||||
}
|
||||
|
||||
if (empty($commit)) {
|
||||
$commit = null;
|
||||
}
|
||||
|
||||
if (empty($commitMessage)) {
|
||||
$commitMessage = null;
|
||||
}
|
||||
|
||||
if (empty($committer)) {
|
||||
$committer = null;
|
||||
}
|
||||
|
||||
$this->createBuild($project, $commit, $branch, $committer, $commitMessage);
|
||||
} catch (\Exception $ex) {
|
||||
$response->setResponseCode(500);
|
||||
$response->setContent(array('status' => 'failed', 'error' => $ex->getMessage()));
|
||||
}
|
||||
|
||||
return $response;
|
||||
return $this->createBuild($project, $commit, $branch, $committer, $commitMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by Github Webhooks:
|
||||
*/
|
||||
public function github($project)
|
||||
public function github($projectId)
|
||||
{
|
||||
$response = new b8\Http\Response\JsonResponse();
|
||||
$response->setContent(array('status' => 'ok'));
|
||||
$project = $this->fetchProject($projectId, 'github');
|
||||
|
||||
switch ($_SERVER['CONTENT_TYPE']) {
|
||||
case 'application/json':
|
||||
$payload = json_decode(file_get_contents('php://input'), true);
|
||||
break;
|
||||
|
||||
case 'application/x-www-form-urlencoded':
|
||||
$payload = json_decode($this->getParam('payload'), true);
|
||||
break;
|
||||
|
||||
default:
|
||||
$response->setResponseCode(401);
|
||||
$response->setContent(array('status' => 'failed', 'error' => 'Content type not supported.'));
|
||||
return $response;
|
||||
return array('status' => 'failed', 'error' => 'Content type not supported.', 'responseCode' => 401);
|
||||
}
|
||||
|
||||
// Handle Pull Request web hooks:
|
||||
if (array_key_exists('pull_request', $payload)) {
|
||||
return $this->githubPullRequest($project, $payload, $response);
|
||||
return $this->githubPullRequest($project, $payload);
|
||||
}
|
||||
|
||||
// Handle Push web hooks:
|
||||
if (array_key_exists('commits', $payload)) {
|
||||
return $this->githubCommitRequest($project, $payload, $response);
|
||||
return $this->githubCommitRequest($project, $payload);
|
||||
}
|
||||
|
||||
return $response;
|
||||
return array('status' => 'ignored', 'message' => 'Unusable payload.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the payload when Github sends a commit webhook.
|
||||
* @param $project
|
||||
*
|
||||
* @param Project $project
|
||||
* @param array $payload
|
||||
* @param b8\Http\Response\JsonResponse $response
|
||||
*
|
||||
* @return b8\Http\Response\JsonResponse
|
||||
*/
|
||||
protected function githubCommitRequest($project, array $payload, b8\Http\Response\JsonResponse $response)
|
||||
protected function githubCommitRequest(Project $project, array $payload)
|
||||
{
|
||||
// Github sends a payload when you close a pull request with a
|
||||
// non-existant commit. We don't want this.
|
||||
if (array_key_exists('after', $payload) && $payload['after'] === '0000000000000000000000000000000000000000') {
|
||||
return $response;
|
||||
return array('status' => 'ignored');
|
||||
}
|
||||
|
||||
try {
|
||||
if (isset($payload['commits']) && is_array($payload['commits'])) {
|
||||
// If we have a list of commits, then add them all as builds to be tested:
|
||||
if (isset($payload['commits']) && is_array($payload['commits'])) {
|
||||
// If we have a list of commits, then add them all as builds to be tested:
|
||||
|
||||
foreach ($payload['commits'] as $commit) {
|
||||
if (!$commit['distinct']) {
|
||||
continue;
|
||||
}
|
||||
$results = array();
|
||||
$status = 'failed';
|
||||
foreach ($payload['commits'] as $commit) {
|
||||
if (!$commit['distinct']) {
|
||||
$results[$commit['id']] = array('status' => 'ignored');
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
$branch = str_replace('refs/heads/', '', $payload['ref']);
|
||||
$committer = $commit['committer']['email'];
|
||||
$this->createBuild($project, $commit['id'], $branch, $committer, $commit['message']);
|
||||
$results[$commit['id']] = $this->createBuild(
|
||||
$project,
|
||||
$commit['id'],
|
||||
$branch,
|
||||
$committer,
|
||||
$commit['message']
|
||||
);
|
||||
$status = 'ok';
|
||||
} catch (Exception $ex) {
|
||||
$results[$commit['id']] = array('status' => 'failed', 'error' => $ex->getMessage());
|
||||
}
|
||||
} elseif (substr($payload['ref'], 0, 10) == 'refs/tags/') {
|
||||
// If we don't, but we're dealing with a tag, add that instead:
|
||||
$branch = str_replace('refs/tags/', 'Tag: ', $payload['ref']);
|
||||
$committer = $payload['pusher']['email'];
|
||||
$message = $payload['head_commit']['message'];
|
||||
$this->createBuild($project, $payload['after'], $branch, $committer, $message);
|
||||
}
|
||||
|
||||
} catch (\Exception $ex) {
|
||||
$response->setResponseCode(500);
|
||||
$response->setContent(array('status' => 'failed', 'error' => $ex->getMessage()));
|
||||
|
||||
return array('status' => $status, 'commits' => $results);
|
||||
}
|
||||
|
||||
return $response;
|
||||
if (substr($payload['ref'], 0, 10) == 'refs/tags/') {
|
||||
// If we don't, but we're dealing with a tag, add that instead:
|
||||
$branch = str_replace('refs/tags/', 'Tag: ', $payload['ref']);
|
||||
$committer = $payload['pusher']['email'];
|
||||
$message = $payload['head_commit']['message'];
|
||||
return $this->createBuild($project, $payload['after'], $branch, $committer, $message);
|
||||
}
|
||||
|
||||
return array('status' => 'ignored', 'message' => 'Unusable payload.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the payload when Github sends a Pull Request webhook.
|
||||
* @param $projectId
|
||||
*
|
||||
* @param Project $project
|
||||
* @param array $payload
|
||||
*/
|
||||
protected function githubPullRequest($projectId, array $payload, b8\Http\Response\JsonResponse $response)
|
||||
protected function githubPullRequest(Project $project, array $payload)
|
||||
{
|
||||
// We only want to know about open pull requests:
|
||||
if (!in_array($payload['action'], array('opened', 'synchronize', 'reopened'))) {
|
||||
return $response;
|
||||
return array('status' => 'ok');
|
||||
}
|
||||
|
||||
try {
|
||||
$headers = array();
|
||||
$token = \b8\Config::getInstance()->get('phpci.github.token');
|
||||
$headers = array();
|
||||
$token = \b8\Config::getInstance()->get('phpci.github.token');
|
||||
|
||||
if (!empty($token)) {
|
||||
$headers[] = 'Authorization: token ' . $token;
|
||||
if (!empty($token)) {
|
||||
$headers[] = 'Authorization: token ' . $token;
|
||||
}
|
||||
|
||||
$url = $payload['pull_request']['commits_url'];
|
||||
$http = new \b8\HttpClient();
|
||||
$http->setHeaders($headers);
|
||||
$response = $http->get($url);
|
||||
|
||||
// Check we got a success response:
|
||||
if (!$response['success']) {
|
||||
throw new Exception('Could not get commits, failed API request.');
|
||||
}
|
||||
|
||||
$results = array();
|
||||
$status = 'failed';
|
||||
foreach ($response['body'] as $commit) {
|
||||
// Skip all but the current HEAD commit ID:
|
||||
$id = $commit['sha'];
|
||||
if ($id != $payload['pull_request']['head']['sha']) {
|
||||
$results[$id] = array('status' => 'ignored', 'message' => 'not branch head');
|
||||
continue;
|
||||
}
|
||||
|
||||
$url = $payload['pull_request']['commits_url'];
|
||||
$http = new \b8\HttpClient();
|
||||
$http->setHeaders($headers);
|
||||
$response = $http->get($url);
|
||||
|
||||
// Check we got a success response:
|
||||
if (!$response['success']) {
|
||||
$message = 'Could not get commits, failed API request.';
|
||||
$response->setResponseCode(500);
|
||||
$response->setContent(array('status' => 'failed', 'error' => $message));
|
||||
return $response;
|
||||
}
|
||||
|
||||
foreach ($response['body'] as $commit) {
|
||||
// Skip all but the current HEAD commit ID:
|
||||
if ($commit['sha'] != $payload['pull_request']['head']['sha']) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
$branch = str_replace('refs/heads/', '', $payload['pull_request']['base']['ref']);
|
||||
$committer = $commit['commit']['author']['email'];
|
||||
$message = $commit['commit']['message'];
|
||||
|
||||
$remoteUrlKey = $payload['pull_request']['head']['repo']['private'] ? 'ssh_url' : 'clone_url';
|
||||
|
||||
$extra = array(
|
||||
'build_type' => 'pull_request',
|
||||
'pull_request_id' => $payload['pull_request']['id'],
|
||||
'pull_request_number' => $payload['number'],
|
||||
'remote_branch' => $payload['pull_request']['head']['ref'],
|
||||
'remote_url' => $payload['pull_request']['head']['repo']['clone_url'],
|
||||
'remote_url' => $payload['pull_request']['head']['repo'][$remoteUrlKey],
|
||||
);
|
||||
|
||||
$this->createBuild($projectId, $commit['sha'], $branch, $committer, $message, $extra);
|
||||
$results[$id] = $this->createBuild($project, $id, $branch, $committer, $message, $extra);
|
||||
$status = 'ok';
|
||||
} catch (Exception $ex) {
|
||||
$results[$id] = array('status' => 'failed', 'error' => $ex->getMessage());
|
||||
}
|
||||
} catch (\Exception $ex) {
|
||||
$response->setResponseCode(500);
|
||||
$response->setContent(array('status' => 'failed', 'error' => $ex->getMessage()));
|
||||
}
|
||||
|
||||
return $response;
|
||||
return array('status' => $status, 'commits' => $results);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by Gitlab Webhooks:
|
||||
*/
|
||||
public function gitlab($project)
|
||||
public function gitlab($projectId)
|
||||
{
|
||||
$response = new b8\Http\Response\JsonResponse();
|
||||
$response->setContent(array('status' => 'ok'));
|
||||
$project = $this->fetchProject($projectId, 'gitlab');
|
||||
|
||||
$payloadString = file_get_contents("php://input");
|
||||
$payload = json_decode($payloadString, true);
|
||||
|
||||
try {
|
||||
// build on merge request events
|
||||
if (isset($payload['object_kind']) && $payload['object_kind'] == 'merge_request') {
|
||||
$attributes = $payload['object_attributes'];
|
||||
if ($attributes['state'] == 'opened' || $attributes['state'] == 'reopened') {
|
||||
$branch = $attributes['source_branch'];
|
||||
$commit = $attributes['last_commit'];
|
||||
$committer = $commit['author']['email'];
|
||||
// build on merge request events
|
||||
if (isset($payload['object_kind']) && $payload['object_kind'] == 'merge_request') {
|
||||
$attributes = $payload['object_attributes'];
|
||||
if ($attributes['state'] == 'opened' || $attributes['state'] == 'reopened') {
|
||||
$branch = $attributes['source_branch'];
|
||||
$commit = $attributes['last_commit'];
|
||||
$committer = $commit['author']['email'];
|
||||
|
||||
$this->createBuild($project, $commit['id'], $branch, $committer, $commit['message']);
|
||||
}
|
||||
return $this->createBuild($project, $commit['id'], $branch, $committer, $commit['message']);
|
||||
}
|
||||
|
||||
// build on push events
|
||||
if (isset($payload['commits']) && is_array($payload['commits'])) {
|
||||
// If we have a list of commits, then add them all as builds to be tested:
|
||||
|
||||
foreach ($payload['commits'] as $commit) {
|
||||
$branch = str_replace('refs/heads/', '', $payload['ref']);
|
||||
$committer = $commit['author']['email'];
|
||||
$this->createBuild($project, $commit['id'], $branch, $committer, $commit['message']);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (\Exception $ex) {
|
||||
$response->setResponseCode(500);
|
||||
$response->setContent(array('status' => 'failed', 'error' => $ex->getMessage()));
|
||||
}
|
||||
|
||||
return $response;
|
||||
// build on push events
|
||||
if (isset($payload['commits']) && is_array($payload['commits'])) {
|
||||
// If we have a list of commits, then add them all as builds to be tested:
|
||||
|
||||
$results = array();
|
||||
$status = 'failed';
|
||||
foreach ($payload['commits'] as $commit) {
|
||||
try {
|
||||
$branch = str_replace('refs/heads/', '', $payload['ref']);
|
||||
$committer = $commit['author']['email'];
|
||||
$results[$commit['id']] = $this->createBuild(
|
||||
$project,
|
||||
$commit['id'],
|
||||
$branch,
|
||||
$committer,
|
||||
$commit['message']
|
||||
);
|
||||
$status = 'ok';
|
||||
} catch (Exception $ex) {
|
||||
$results[$commit['id']] = array('status' => 'failed', 'error' => $ex->getMessage());
|
||||
}
|
||||
}
|
||||
return array('status' => $status, 'commits' => $results);
|
||||
}
|
||||
|
||||
return array('status' => 'ignored', 'message' => 'Unusable payload.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for creating a new build.
|
||||
* @param $projectId
|
||||
* @param $commitId
|
||||
* @param $branch
|
||||
* @param $committer
|
||||
* @param $commitMessage
|
||||
* @param null $extra
|
||||
* @return bool
|
||||
* @throws \Exception
|
||||
*
|
||||
* @param Project $project
|
||||
* @param string $commitId
|
||||
* @param string $branch
|
||||
* @param string $committer
|
||||
* @param string $commitMessage
|
||||
* @param array $extra
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function createBuild($projectId, $commitId, $branch, $committer, $commitMessage, $extra = null)
|
||||
{
|
||||
protected function createBuild(
|
||||
Project $project,
|
||||
$commitId,
|
||||
$branch,
|
||||
$committer,
|
||||
$commitMessage,
|
||||
array $extra = null
|
||||
) {
|
||||
// Check if a build already exists for this commit ID:
|
||||
$builds = $this->buildStore->getByProjectAndCommit($projectId, $commitId);
|
||||
$builds = $this->buildStore->getByProjectAndCommit($project->getId(), $commitId);
|
||||
|
||||
if ($builds['count']) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$project = $this->projectStore->getById($projectId);
|
||||
|
||||
if (empty($project)) {
|
||||
throw new \Exception('Project does not exist:' . $projectId);
|
||||
return array(
|
||||
'status' => 'ignored',
|
||||
'message' => sprintf('Duplicate of build #%d', $builds['items'][0]->getId())
|
||||
);
|
||||
}
|
||||
|
||||
// If not, create a new build job for it:
|
||||
|
@ -335,6 +369,34 @@ class WebhookController extends \PHPCI\Controller
|
|||
// Send a status postback if the build type provides one:
|
||||
$build->sendStatusPostback();
|
||||
|
||||
return true;
|
||||
return array('status' => 'ok', 'buildID' => $build->getID());
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch a project and check its type.
|
||||
*
|
||||
* @param int $projectId
|
||||
* @param array|string $expectedType
|
||||
*
|
||||
* @return Project
|
||||
*
|
||||
* @throws Exception If the project does not exist or is not of the expected type.
|
||||
*/
|
||||
protected function fetchProject($projectId, $expectedType)
|
||||
{
|
||||
$project = $this->projectStore->getById($projectId);
|
||||
|
||||
if (empty($projectId)) {
|
||||
throw new Exception('Project does not exist: ' . $projectId);
|
||||
}
|
||||
|
||||
if (is_array($expectedType)
|
||||
? !in_array($project->getType(), $expectedType)
|
||||
: $project->getType() !== $expectedType
|
||||
) {
|
||||
throw new Exception('Wrong project type: ' . $project->getType());
|
||||
}
|
||||
|
||||
return $project;
|
||||
}
|
||||
}
|
||||
|
|
68
PHPCI/ErrorHandler.php
Normal file
68
PHPCI/ErrorHandler.php
Normal file
|
@ -0,0 +1,68 @@
|
|||
<?php
|
||||
/**
|
||||
* 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/
|
||||
*/
|
||||
|
||||
namespace PHPCI;
|
||||
|
||||
/**
|
||||
* Error Handler
|
||||
*
|
||||
* @package PHPCI\Logging
|
||||
*/
|
||||
class ErrorHandler
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $levels = array(
|
||||
E_WARNING => 'Warning',
|
||||
E_NOTICE => 'Notice',
|
||||
E_USER_ERROR => 'User Error',
|
||||
E_USER_WARNING => 'User Warning',
|
||||
E_USER_NOTICE => 'User Notice',
|
||||
E_STRICT => 'Runtime Notice',
|
||||
E_RECOVERABLE_ERROR => 'Catchable Fatal Error',
|
||||
E_DEPRECATED => 'Deprecated',
|
||||
E_USER_DEPRECATED => 'User Deprecated',
|
||||
);
|
||||
|
||||
/**
|
||||
* Registers an instance of the error handler to throw ErrorException.
|
||||
*/
|
||||
public static function register()
|
||||
{
|
||||
$handler = new static();
|
||||
set_error_handler(array($handler, 'handleError'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param integer $level
|
||||
* @param string $message
|
||||
* @param string $file
|
||||
* @param integer $line
|
||||
*
|
||||
* @throws \ErrorException
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public function handleError($level, $message, $file, $line)
|
||||
{
|
||||
if (error_reporting() & $level === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$exceptionLevel = isset($this->levels[$level]) ? $this->levels[$level] : $level;
|
||||
throw new \ErrorException(
|
||||
sprintf('%s: %s in %s line %d', $exceptionLevel, $message, $file, $line),
|
||||
0,
|
||||
$level,
|
||||
$file,
|
||||
$line
|
||||
);
|
||||
}
|
||||
}
|
55
PHPCI/Helper/AnsiConverter.php
Normal file
55
PHPCI/Helper/AnsiConverter.php
Normal file
|
@ -0,0 +1,55 @@
|
|||
<?php
|
||||
/**
|
||||
* 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/
|
||||
*/
|
||||
|
||||
namespace PHPCI\Helper;
|
||||
|
||||
use SensioLabs\AnsiConverter\AnsiToHtmlConverter;
|
||||
|
||||
/**
|
||||
* Converts ANSI output to HTML.
|
||||
*
|
||||
* @package PHPCI\Helper
|
||||
*/
|
||||
final class AnsiConverter
|
||||
{
|
||||
static private $converter = null;
|
||||
|
||||
/**
|
||||
* Initialize the singletion.
|
||||
*
|
||||
* @return AnsiToHtmlConverter
|
||||
*/
|
||||
private static function getInstance()
|
||||
{
|
||||
if (self::$converter === null) {
|
||||
self::$converter = new AnsiToHtmlConverter(null, false);
|
||||
}
|
||||
|
||||
return self::$converter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a text containing ANSI colr sequences into HTML code.
|
||||
*
|
||||
* @param string $text The text to convert
|
||||
*
|
||||
* @return string The HTML code.
|
||||
*/
|
||||
public static function convert($text)
|
||||
{
|
||||
return self::getInstance()->convert($text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Do not instanciate this class.
|
||||
*/
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
}
|
|
@ -9,9 +9,9 @@
|
|||
|
||||
namespace PHPCI\Helper;
|
||||
|
||||
use \PHPCI\Logging\BuildLogger;
|
||||
use Exception;
|
||||
use PHPCI\Logging\BuildLogger;
|
||||
use Psr\Log\LogLevel;
|
||||
use PHPCI\Helper\Lang;
|
||||
|
||||
/**
|
||||
* Handles running system commands with variables.
|
||||
|
@ -20,7 +20,7 @@ use PHPCI\Helper\Lang;
|
|||
abstract class BaseCommandExecutor implements CommandExecutor
|
||||
{
|
||||
/**
|
||||
* @var \PHPCI\Logging\BuildLogger
|
||||
* @var BuildLogger
|
||||
*/
|
||||
protected $logger;
|
||||
|
||||
|
@ -144,13 +144,12 @@ abstract class BaseCommandExecutor implements CommandExecutor
|
|||
/**
|
||||
* Find a binary required by a plugin.
|
||||
* @param string $binary
|
||||
* @param null $buildPath
|
||||
* @param bool $quiet
|
||||
* @return null|string
|
||||
*/
|
||||
public function findBinary($binary, $buildPath = null)
|
||||
public function findBinary($binary, $quiet = false)
|
||||
{
|
||||
$binaryPath = null;
|
||||
$composerBin = $this->getComposerBinDir(realpath($buildPath));
|
||||
$composerBin = $this->getComposerBinDir(realpath($this->buildPath));
|
||||
|
||||
if (is_string($binary)) {
|
||||
$binary = array($binary);
|
||||
|
@ -161,30 +160,30 @@ abstract class BaseCommandExecutor implements CommandExecutor
|
|||
|
||||
if (is_dir($composerBin) && is_file($composerBin.'/'.$bin)) {
|
||||
$this->logger->log(Lang::get('found_in_path', $composerBin, $bin), LogLevel::DEBUG);
|
||||
$binaryPath = $composerBin . '/' . $bin;
|
||||
break;
|
||||
return $composerBin . '/' . $bin;
|
||||
}
|
||||
|
||||
if (is_file($this->rootDir . $bin)) {
|
||||
$this->logger->log(Lang::get('found_in_path', 'root', $bin), LogLevel::DEBUG);
|
||||
$binaryPath = $this->rootDir . $bin;
|
||||
break;
|
||||
return $this->rootDir . $bin;
|
||||
}
|
||||
|
||||
if (is_file($this->rootDir . 'vendor/bin/' . $bin)) {
|
||||
$this->logger->log(Lang::get('found_in_path', 'vendor/bin', $bin), LogLevel::DEBUG);
|
||||
$binaryPath = $this->rootDir . 'vendor/bin/' . $bin;
|
||||
break;
|
||||
return $this->rootDir . 'vendor/bin/' . $bin;
|
||||
}
|
||||
|
||||
$findCmdResult = $this->findGlobalBinary($bin);
|
||||
if (is_file($findCmdResult)) {
|
||||
$this->logger->log(Lang::get('found_in_path', '', $bin), LogLevel::DEBUG);
|
||||
$binaryPath = $findCmdResult;
|
||||
break;
|
||||
return $findCmdResult;
|
||||
}
|
||||
}
|
||||
return $binaryPath;
|
||||
|
||||
if ($quiet) {
|
||||
return;
|
||||
}
|
||||
throw new Exception(Lang::get('could_not_find', implode('/', $binary)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -26,10 +26,13 @@ interface CommandExecutor
|
|||
/**
|
||||
* Find a binary required by a plugin.
|
||||
* @param string $binary
|
||||
* @param string $buildPath the current build path
|
||||
* @param bool $quiet Returns null instead of throwing an execption.
|
||||
*
|
||||
* @return null|string
|
||||
*
|
||||
* @throws \Exception when no binary has been found and $quiet is false.
|
||||
*/
|
||||
public function findBinary($binary, $buildPath = null);
|
||||
public function findBinary($binary, $quiet = false);
|
||||
|
||||
/**
|
||||
* Set the buildPath property.
|
||||
|
|
|
@ -156,7 +156,7 @@ class Lang
|
|||
return null;
|
||||
}
|
||||
|
||||
require_once($langFile);
|
||||
require($langFile);
|
||||
|
||||
if (is_null($strings) || !is_array($strings) || !count($strings)) {
|
||||
return null;
|
||||
|
|
|
@ -39,6 +39,7 @@ PHPCI',
|
|||
'reset_email_title' => 'PHPCI Adgangskode-nulstilling for %s',
|
||||
'reset_invalid' => 'Ugyldig anmodning om adgangskode-nulstilling.',
|
||||
'email_address' => 'Email-addresse',
|
||||
'login' => 'Login / Email Address',
|
||||
'password' => 'Adgangskode',
|
||||
'log_in' => 'Log ind',
|
||||
|
||||
|
@ -126,6 +127,7 @@ i din foretrukne hosting-platform.',
|
|||
'all_branches' => 'Alle branches',
|
||||
'builds' => 'Builds',
|
||||
'id' => 'ID',
|
||||
'date' => 'Date',
|
||||
'project' => 'Projekt',
|
||||
'commit' => 'Commit',
|
||||
'branch' => 'Branch',
|
||||
|
@ -193,14 +195,20 @@ Services</a> sektionen under dit Bitbucket-repository.',
|
|||
'end' => 'Slut',
|
||||
'from' => 'Fra',
|
||||
'to' => 'Til',
|
||||
'suite' => 'Suite',
|
||||
'test' => 'Test',
|
||||
'result' => 'Resultat',
|
||||
'ok' => 'OK',
|
||||
'took_n_seconds' => 'Tog %d sekunder',
|
||||
'build_created' => 'Build Oprettet',
|
||||
'build_started' => 'Build Startet',
|
||||
'build_finished' => 'Build Afsluttet',
|
||||
'test_message' => 'Message',
|
||||
'test_no_message' => 'No message',
|
||||
'test_success' => 'Succesfull: %d',
|
||||
'test_fail' => 'Failures: %d',
|
||||
'test_skipped' => 'Skipped: %d',
|
||||
'test_error' => 'Errors: %d',
|
||||
'test_todo' => 'Todos: %d',
|
||||
'test_total' => '%d test(s)',
|
||||
|
||||
// Users
|
||||
'name' => 'Navn',
|
||||
|
@ -296,15 +304,15 @@ du kører composer update.',
|
|||
Kontrollér venligst nedenstående fejl før du fortsætter.',
|
||||
'must_be_valid_email' => 'Skal være en gyldig email-adresse.',
|
||||
'must_be_valid_url' => 'Skal være en gyldig URL.',
|
||||
'enter_name' => 'Administrator-navn:',
|
||||
'enter_email' => 'Administrators email-adresse:',
|
||||
'enter_password' => 'Administrator-adgangskode:',
|
||||
'enter_phpci_url' => 'Din PHPCI URL (eksempelvis "http://phpci.local"):',
|
||||
'enter_name' => 'Administrator-navn: ',
|
||||
'enter_email' => 'Administrators email-adresse: ',
|
||||
'enter_password' => 'Administrator-adgangskode: ',
|
||||
'enter_phpci_url' => 'Din PHPCI URL (eksempelvis "http://phpci.local"): ',
|
||||
|
||||
'enter_db_host' => 'Indtast dit MySQL-hostnavn [localhost]:',
|
||||
'enter_db_name' => 'Indtast dit MySQL database-navn [phpci]:',
|
||||
'enter_db_user' => 'Indtast dit MySQL-brugernavn [phpci]:',
|
||||
'enter_db_pass' => 'Indtast dit MySQL-password:',
|
||||
'enter_db_host' => 'Indtast dit MySQL-hostnavn [localhost]: ',
|
||||
'enter_db_name' => 'Indtast dit MySQL database-navn [phpci]: ',
|
||||
'enter_db_user' => 'Indtast dit MySQL-brugernavn [phpci]: ',
|
||||
'enter_db_pass' => 'Indtast dit MySQL-password: ',
|
||||
'could_not_connect' => 'PHPCI kunne ikke forbinde til MySQL med de angivning oplysninger. Forsøg igen.',
|
||||
'setting_up_db' => 'Indlæser database...',
|
||||
'user_created' => 'Brugerkonto oprettet!',
|
||||
|
@ -331,6 +339,12 @@ Kontrollér venligst nedenstående fejl før du fortsætter.',
|
|||
'create_admin_user' => 'Tilføj en administrator',
|
||||
'incorrect_format' => 'Forkert format',
|
||||
|
||||
// Create Build Command
|
||||
'create_build_project' => 'Create a build for a project',
|
||||
'project_id_argument' => 'A project ID',
|
||||
'commit_id_option' => 'Commit ID to build',
|
||||
'branch_name_option' => 'Branch to build',
|
||||
|
||||
// Run Command
|
||||
'run_all_pending' => 'Kør alle PHPCI builds i køen.',
|
||||
'finding_builds' => 'Finder builds der skal køres',
|
||||
|
|
|
@ -39,6 +39,7 @@ PHPCI',
|
|||
'reset_email_title' => 'PHPCI Passwort zurücksetzen für %s',
|
||||
'reset_invalid' => 'Fehlerhafte Anfrage für das Zurücksetzen eines Passwortes',
|
||||
'email_address' => 'Emailadresse',
|
||||
'login' => 'Login / Email Address',
|
||||
'password' => 'Passwort',
|
||||
'log_in' => 'Einloggen',
|
||||
|
||||
|
@ -101,7 +102,8 @@ generiert. Um es zu verwenden, fügen Sie einfach den folgenden Public Key im Ab
|
|||
'remote' => 'Externe URL',
|
||||
'local' => 'Lokaler Pfad',
|
||||
'hg' => 'Mercurial',
|
||||
|
||||
'svn' => 'Subversion',
|
||||
|
||||
'where_hosted' => 'Wo wird Ihr Projekt gehostet?',
|
||||
'choose_github' => 'Wählen Sie ein GitHub Repository:',
|
||||
|
||||
|
@ -127,6 +129,7 @@ generiert. Um es zu verwenden, fügen Sie einfach den folgenden Public Key im Ab
|
|||
'all_branches' => 'Alle Branches',
|
||||
'builds' => 'Builds',
|
||||
'id' => 'ID',
|
||||
'date' => 'Date',
|
||||
'project' => 'Projekt',
|
||||
'commit' => 'Commit',
|
||||
'branch' => 'Branch',
|
||||
|
@ -181,7 +184,15 @@ generiert. Um es zu verwenden, fügen Sie einfach den folgenden Public Key im Ab
|
|||
'phpmd' => 'PHP Mess Detector',
|
||||
'phpspec' => 'PHP Spec',
|
||||
'phpunit' => 'PHP Unit',
|
||||
'technical_debt' => 'Technische Schulden',
|
||||
'behat' => 'Behat',
|
||||
|
||||
'codeception_feature' => 'Feature',
|
||||
'codeception_suite' => 'Suite',
|
||||
'codeception_time' => 'Zeit',
|
||||
'codeception_synopsis' => '<strong>%1$d</strong> Tests in <strong>%2$f</strong> Sekunden ausgeführt.
|
||||
<strong>%3$d</strong> Fehler.',
|
||||
|
||||
'file' => 'Datei',
|
||||
'line' => 'Zeile',
|
||||
'class' => 'Klasse',
|
||||
|
@ -191,14 +202,20 @@ generiert. Um es zu verwenden, fügen Sie einfach den folgenden Public Key im Ab
|
|||
'end' => 'Ende',
|
||||
'from' => 'Von',
|
||||
'to' => 'Bis',
|
||||
'suite' => 'Suite',
|
||||
'test' => 'Test',
|
||||
'result' => 'Resultat',
|
||||
'ok' => 'OK',
|
||||
'took_n_seconds' => 'Benötigte %d Sekunden',
|
||||
'build_created' => 'Build erstellt',
|
||||
'build_started' => 'Build gestartet',
|
||||
'build_finished' => 'Build abgeschlossen',
|
||||
'test_message' => 'Message',
|
||||
'test_no_message' => 'No message',
|
||||
'test_success' => 'Succesfull: %d',
|
||||
'test_fail' => 'Failures: %d',
|
||||
'test_skipped' => 'Skipped: %d',
|
||||
'test_error' => 'Errors: %d',
|
||||
'test_todo' => 'Todos: %d',
|
||||
'test_total' => '%d test(s)',
|
||||
|
||||
// Users
|
||||
'name' => 'Name',
|
||||
|
@ -294,9 +311,9 @@ generiert. Um es zu verwenden, fügen Sie einfach den folgenden Public Key im Ab
|
|||
Bitte überprüfen Sie die Fehler, bevor Sie fortfahren,',
|
||||
'must_be_valid_email' => 'Muss eine gültige Emailadresse sein.',
|
||||
'must_be_valid_url' => 'Muss eine valide URL sein.',
|
||||
'enter_name' => 'Name des Administrators:',
|
||||
'enter_email' => 'Emailadresse des Administrators:',
|
||||
'enter_password' => 'Passwort des Administrators:',
|
||||
'enter_name' => 'Name des Administrators: ',
|
||||
'enter_email' => 'Emailadresse des Administrators: ',
|
||||
'enter_password' => 'Passwort des Administrators: ',
|
||||
'enter_phpci_url' => 'Ihre PHPCI-URL (z.B. "http://phpci.local"): ',
|
||||
|
||||
'enter_db_host' => 'Bitte geben Sie Ihren MySQL-Host ein [localhost]: ',
|
||||
|
@ -329,6 +346,12 @@ generiert. Um es zu verwenden, fügen Sie einfach den folgenden Public Key im Ab
|
|||
'create_admin_user' => 'Administratorenbenutzer erstellen',
|
||||
'incorrect_format' => 'Falsches Format',
|
||||
|
||||
// Create Build Command
|
||||
'create_build_project' => 'Create a build for a project',
|
||||
'project_id_argument' => 'A project ID',
|
||||
'commit_id_option' => 'Commit ID to build',
|
||||
'branch_name_option' => 'Branch to build',
|
||||
|
||||
// Run Command
|
||||
'run_all_pending' => 'Führe alle ausstehenden PHPCI Builds aus.',
|
||||
'finding_builds' => 'Suche verarbeitbare Builds',
|
||||
|
|
|
@ -39,6 +39,7 @@ PHPCI',
|
|||
'reset_email_title' => 'PHPCI Επαναφορά Κωδικού για %s',
|
||||
'reset_invalid' => 'Μη έγκυρο αίτημα επαναφοράς κωδικού πρόσβασης.',
|
||||
'email_address' => 'Διεύθυνση email',
|
||||
'login' => 'Login / Email Address',
|
||||
'password' => 'Κωδικός πρόσβασης',
|
||||
'log_in' => 'Είσοδος',
|
||||
|
||||
|
@ -127,6 +128,7 @@ PHPCI',
|
|||
'all_branches' => 'Όλες οι διακλαδώσεις',
|
||||
'builds' => 'Κατασκευές',
|
||||
'id' => 'Αριθμός αναγνώρισης',
|
||||
'date' => 'Date',
|
||||
'project' => 'Έργο',
|
||||
'commit' => 'Συνεισφορά',
|
||||
'branch' => 'Διακλάδωση',
|
||||
|
@ -170,6 +172,7 @@ Services</a> του Bitbucket αποθετηρίου σας.',
|
|||
'codeception_errors' => 'Λάθη Codeception',
|
||||
'phpmd_warnings' => 'Προειδοποιήσεις PHPMD',
|
||||
'phpcs_warnings' => 'Προειδοποιήσεις PHPCS ',
|
||||
'codeception_errors' => 'Λάθη Codeception',
|
||||
'phpcs_errors' => 'Λάθη PHPCS',
|
||||
'phplint_errors' => 'Λάθη Lint',
|
||||
'phpunit_errors' => 'Λάθη PHPUnit ',
|
||||
|
@ -193,14 +196,20 @@ Services</a> του Bitbucket αποθετηρίου σας.',
|
|||
'end' => 'Τέλος',
|
||||
'from' => 'Από',
|
||||
'to' => 'Προς',
|
||||
'suite' => 'Σουίτα',
|
||||
'test' => 'Τέστ',
|
||||
'result' => 'Αποτέλεσμα',
|
||||
'ok' => 'ΟΚ',
|
||||
'took_n_seconds' => 'Χρειάστηκαν %d δευτερόλεπτα',
|
||||
'build_created' => 'Η κατασκευή δημιουργήθηκε',
|
||||
'build_started' => 'Η κατασκευή άρχισε',
|
||||
'build_finished' => 'Η κατασκευή ολοκληρώθηκε',
|
||||
'test_message' => 'Message',
|
||||
'test_no_message' => 'No message',
|
||||
'test_success' => 'Succesfull: %d',
|
||||
'test_fail' => 'Failures: %d',
|
||||
'test_skipped' => 'Skipped: %d',
|
||||
'test_error' => 'Errors: %d',
|
||||
'test_todo' => 'Todos: %d',
|
||||
'test_total' => '%d test(s)',
|
||||
|
||||
// Users
|
||||
'name' => 'Όνομα',
|
||||
|
@ -297,15 +306,15 @@ Services</a> του Bitbucket αποθετηρίου σας.',
|
|||
Παρακαλούμε διαβάστε τα παραπάνω λάθη πριν συνεχίσετε.',
|
||||
'must_be_valid_email' => 'Πρέπει να είναι μια έγκυρη διεύθυνση ηλεκτρονικού ταχυδρομείου.',
|
||||
'must_be_valid_url' => 'Πρέπει να είναι μια έγκυρη διεύθυνση URL.',
|
||||
'enter_name' => 'Όνομα διαχειριστή:',
|
||||
'enter_email' => 'Ηλ. Διεύθυνση διαχειριστή:',
|
||||
'enter_password' => 'Κωδικός πρόσβασης διαχειριστή:',
|
||||
'enter_name' => 'Όνομα διαχειριστή: ',
|
||||
'enter_email' => 'Ηλ. Διεύθυνση διαχειριστή: ',
|
||||
'enter_password' => 'Κωδικός πρόσβασης διαχειριστή: ',
|
||||
'enter_phpci_url' => 'Ο URL σύνδεσμος σας για το PHPCI ("http://phpci.local" για παράδειγμα): ',
|
||||
|
||||
'enter_db_host' => 'Παρακαλώ εισάγετε τον MySQL οικοδεσπότη σας [localhost]:',
|
||||
'enter_db_host' => 'Παρακαλώ εισάγετε τον MySQL οικοδεσπότη σας [localhost]: ',
|
||||
'enter_db_name' => 'Παρακαλώ εισάγετε το όνομα της MySQL βάσης δεδομένων σας [phpci]: ',
|
||||
'enter_db_user' => 'Παρακαλώ εισάγετε το όνομα χρήστη της MySQL σας [phpci]:',
|
||||
'enter_db_pass' => 'Παρακαλώ εισάγετε τον κωδικό χρήστη της MySQL σας:',
|
||||
'enter_db_user' => 'Παρακαλώ εισάγετε το όνομα χρήστη της MySQL σας [phpci]: ',
|
||||
'enter_db_pass' => 'Παρακαλώ εισάγετε τον κωδικό χρήστη της MySQL σας: ',
|
||||
'could_not_connect' => 'Το PHPCI δεν μπόρεσε να συνδεθεί με την MySQL με τα στοχεία που δώσατε. Παρακαλώ δοκιμάστε ξανά.',
|
||||
'setting_up_db' => 'Γίνεται ρύθμιση της βάσης δεδομένων σας ...',
|
||||
'user_created' => 'Λογαριασμός χρήστη δημιουργήθηκε!',
|
||||
|
@ -332,6 +341,12 @@ Services</a> του Bitbucket αποθετηρίου σας.',
|
|||
'create_admin_user' => 'Δημιουργήστε ένα χρήστη διαχειριστή',
|
||||
'incorrect_format' => 'Λανθασμένη μορφοποίηση',
|
||||
|
||||
// Create Build Command
|
||||
'create_build_project' => 'Create a build for a project',
|
||||
'project_id_argument' => 'A project ID',
|
||||
'commit_id_option' => 'Commit ID to build',
|
||||
'branch_name_option' => 'Branch to build',
|
||||
|
||||
// Run Command
|
||||
'run_all_pending' => 'Εκτελέστε όλες τις εκκρεμείς PHPCI κατασκευές.',
|
||||
'finding_builds' => 'Αναζήτηση κατασκευών για επεξεργασία',
|
||||
|
|
|
@ -39,6 +39,7 @@ PHPCI',
|
|||
'reset_email_title' => 'PHPCI Password Reset for %s',
|
||||
'reset_invalid' => 'Invalid password reset request.',
|
||||
'email_address' => 'Email Address',
|
||||
'login' => 'Login / Email Address',
|
||||
'password' => 'Password',
|
||||
'log_in' => 'Log in',
|
||||
|
||||
|
@ -128,6 +129,7 @@ PHPCI',
|
|||
'all_branches' => 'All Branches',
|
||||
'builds' => 'Builds',
|
||||
'id' => 'ID',
|
||||
'date' => 'Date',
|
||||
'project' => 'Project',
|
||||
'commit' => 'Commit',
|
||||
'branch' => 'Branch',
|
||||
|
@ -188,6 +190,12 @@ PHPCI',
|
|||
'technical_debt' => 'Technical Debt',
|
||||
'behat' => 'Behat',
|
||||
|
||||
'codeception_feature' => 'Feature',
|
||||
'codeception_suite' => 'Suite',
|
||||
'codeception_time' => 'Time',
|
||||
'codeception_synopsis' => '<strong>%1$d</strong> tests carried out in <strong>%2$f</strong> seconds.
|
||||
<strong>%3$d</strong> failures.',
|
||||
|
||||
'file' => 'File',
|
||||
'line' => 'Line',
|
||||
'class' => 'Class',
|
||||
|
@ -197,14 +205,20 @@ PHPCI',
|
|||
'end' => 'End',
|
||||
'from' => 'From',
|
||||
'to' => 'To',
|
||||
'suite' => 'Suite',
|
||||
'test' => 'Test',
|
||||
'result' => 'Result',
|
||||
'ok' => 'OK',
|
||||
'took_n_seconds' => 'Took %d seconds',
|
||||
'build_created' => 'Build Created',
|
||||
'build_started' => 'Build Started',
|
||||
'build_finished' => 'Build Finished',
|
||||
'test_message' => 'Message',
|
||||
'test_no_message' => 'No message',
|
||||
'test_success' => 'Succesfull: %d',
|
||||
'test_fail' => 'Failures: %d',
|
||||
'test_skipped' => 'Skipped: %d',
|
||||
'test_error' => 'Errors: %d',
|
||||
'test_todo' => 'Todos: %d',
|
||||
'test_total' => '%d test(s)',
|
||||
|
||||
// Users
|
||||
'name' => 'Name',
|
||||
|
@ -281,6 +295,17 @@ PHPCI',
|
|||
'search_packagist_for_more' => 'Search Packagist for more packages',
|
||||
'search' => 'Search »',
|
||||
|
||||
// Summary plugin
|
||||
'build-summary' => 'Summary',
|
||||
'stage' => 'Stage',
|
||||
'duration' => 'Duration',
|
||||
'plugin' => 'Plugin',
|
||||
'stage_setup' => 'Setup',
|
||||
'stage_test' => 'Test',
|
||||
'stage_complete' => 'Complete',
|
||||
'stage_success' => 'Success',
|
||||
'stage_failure' => 'Failure',
|
||||
|
||||
// Installer
|
||||
'installation_url' => 'PHPCI Installation URL',
|
||||
'db_host' => 'Database Host',
|
||||
|
@ -301,9 +326,9 @@ PHPCI',
|
|||
Please review the errors above before continuing.',
|
||||
'must_be_valid_email' => 'Must be a valid email address.',
|
||||
'must_be_valid_url' => 'Must be a valid URL.',
|
||||
'enter_name' => 'Admin Name:',
|
||||
'enter_email' => 'Admin Email:',
|
||||
'enter_password' => 'Admin Password:',
|
||||
'enter_name' => 'Admin Name: ',
|
||||
'enter_email' => 'Admin Email: ',
|
||||
'enter_password' => 'Admin Password: ',
|
||||
'enter_phpci_url' => 'Your PHPCI URL ("http://phpci.local" for example): ',
|
||||
|
||||
'enter_db_host' => 'Please enter your MySQL host [localhost]: ',
|
||||
|
@ -336,6 +361,12 @@ PHPCI',
|
|||
'create_admin_user' => 'Create an admin user',
|
||||
'incorrect_format' => 'Incorrect format',
|
||||
|
||||
// Create Build Command
|
||||
'create_build_project' => 'Create a build for a project',
|
||||
'project_id_argument' => 'A project ID',
|
||||
'commit_id_option' => 'Commit ID to build',
|
||||
'branch_name_option' => 'Branch to build',
|
||||
|
||||
// Run Command
|
||||
'run_all_pending' => 'Run all pending PHPCI builds.',
|
||||
'finding_builds' => 'Finding builds to process',
|
||||
|
|
386
PHPCI/Languages/lang.es.php
Normal file
386
PHPCI/Languages/lang.es.php
Normal file
|
@ -0,0 +1,386 @@
|
|||
<?php
|
||||
/**
|
||||
* 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/
|
||||
*/
|
||||
|
||||
$strings = array(
|
||||
'language_name' => 'Español',
|
||||
'language' => 'Lenguaje',
|
||||
|
||||
// Log in:
|
||||
'log_in_to_phpci' => 'Ingresar a PHPCI',
|
||||
'login_error' => 'Email o contraseña incorrectos',
|
||||
'forgotten_password_link' => '¿Olvidaste tu contraseña?',
|
||||
'reset_emailed' => 'Te hemos enviado un email para reiniciar tu contraseña.',
|
||||
'reset_header' => '<strong>¡No te preocupes!</strong><br>Solo tienes que ingresar tu dirección de email
|
||||
y te enviaremos por email un enlace para reiniciar tu contraseña.',
|
||||
'reset_email_address' => 'Ingresa tu dirección de email:',
|
||||
'reset_send_email' => 'Enviar enlace',
|
||||
'reset_enter_password' => 'Ingresa una nueva contraseña',
|
||||
'reset_new_password' => 'Nueva contraseña:',
|
||||
'reset_change_password' => 'Cambiar contraseña',
|
||||
'reset_no_user_exists' => 'No existe ningún usuario con ese email, por favor intenta nuevamente.',
|
||||
'reset_email_body' => 'Hola %s,
|
||||
|
||||
Has recibido este correo porque tú, o alguien más, ha solicitado reiniciar la contraseña de PHPCI
|
||||
|
||||
Si fuiste tú, por favor haz click en el siguiente enlace para reiniciar tu contraseña: %ssession/reset-password/%d/%s
|
||||
|
||||
De lo contrario, por favor ignora este correo y ninguna acción será realizada.
|
||||
|
||||
Gracias,
|
||||
|
||||
PHPCI',
|
||||
|
||||
'reset_email_title' => 'Reiniciar contraseña de PHPCI para %s',
|
||||
'reset_invalid' => 'Pedido inválido.',
|
||||
'email_address' => 'Dirección de email',
|
||||
'password' => 'Contraseña',
|
||||
'log_in' => 'Ingresar',
|
||||
|
||||
|
||||
// Top Nav
|
||||
'toggle_navigation' => 'Activar navegación',
|
||||
'n_builds_pending' => '%d builds pendientes',
|
||||
'n_builds_running' => '%d builds ejecutándose',
|
||||
'edit_profile' => 'Editar Perfil',
|
||||
'sign_out' => 'Cerrar Sesión',
|
||||
'branch_x' => 'Rama: %s',
|
||||
'created_x' => 'Creada el: %s',
|
||||
'started_x' => 'Comenzó: %s',
|
||||
|
||||
// Sidebar
|
||||
'hello_name' => 'Hola, %s',
|
||||
'dashboard' => 'Escritorio',
|
||||
'admin_options' => 'Opciones de Admin.',
|
||||
'add_project' => 'Agregar Proyecto',
|
||||
'settings' => 'Configuración',
|
||||
'manage_users' => 'Administrar Usuarios',
|
||||
'plugins' => 'Plugins',
|
||||
'view' => 'Vista',
|
||||
'build_now' => 'Ejecutar Build',
|
||||
'edit_project' => 'Editar Proyecto',
|
||||
'delete_project' => 'Eliminar Proyecto',
|
||||
|
||||
// Project Summary:
|
||||
'no_builds_yet' => '¡No existen builds aún!',
|
||||
'x_of_x_failed' => '%d de los últimos %d builds fallaron.',
|
||||
'x_of_x_failed_short' => '%d / %d fallaron.',
|
||||
'last_successful_build' => ' El último build exitoso fue %s.',
|
||||
'never_built_successfully' => ' Este proyecto nunca tuvo un build exitoso.',
|
||||
'all_builds_passed' => 'Todos los últimos %d builds pasaron.',
|
||||
'all_builds_passed_short' => '%d / %d pasaron.',
|
||||
'last_failed_build' => ' El último build en fallar fue %s.',
|
||||
'never_failed_build' => ' Este proyecto no tiene ningún build fallido.',
|
||||
'view_project' => 'Ver Proyecto',
|
||||
|
||||
// Timeline:
|
||||
'latest_builds' => 'Últimos builds',
|
||||
'pending' => 'Pediente',
|
||||
'running' => 'Ejecutando',
|
||||
'success' => 'Éxito',
|
||||
'successful' => 'Exitoso',
|
||||
'failed' => 'Falló',
|
||||
'manual_build' => 'Build Manual',
|
||||
|
||||
// Add/Edit Project:
|
||||
'new_project' => 'Nuevo Proyecto',
|
||||
'project_x_not_found' => 'El Proyecto con ID %d no existe.',
|
||||
'project_details' => 'Detalles del Proyecto',
|
||||
'public_key_help' => 'Para facilitarte, hemos generado un par de llaves SSH para que uses en este proyecto.
|
||||
Para usarlo, sólo agrega la siguiente llave pública a la sección de "deploy keys"
|
||||
de tu plataforma de hosting de versionado de código.',
|
||||
'select_repository_type' => 'Selecciona tipo de repositorio...',
|
||||
'github' => 'GitHub',
|
||||
'bitbucket' => 'Bitbucket',
|
||||
'gitlab' => 'GitLab',
|
||||
'remote' => 'URL Remota',
|
||||
'local' => 'Path local',
|
||||
'hg' => 'Mercurial',
|
||||
'svn' => 'Subversion',
|
||||
|
||||
'where_hosted' => '¿Dónde está alojado tu proyecto?',
|
||||
'choose_github' => 'Selecciona un repositorio de GitHub:',
|
||||
|
||||
'repo_name' => 'Nombre del repositorio / URL (Remoto) o Ruta (Local)',
|
||||
'project_title' => 'Titulo del proyecto',
|
||||
'project_private_key' => 'Clave privada a usar para acceder al repositorio
|
||||
(dejar en blanco para remotos locales o anónimos)',
|
||||
'build_config' => 'Configuración PHPCI para builds del proyecto
|
||||
(en caso que no puedas agregar el archivo phpci.yml al repositorio)',
|
||||
'default_branch' => 'Nombre de la rama por defecto',
|
||||
'allow_public_status' => '¿Activar página pública con el estado del proyecto?',
|
||||
'archived' => 'Archivado',
|
||||
'save_project' => 'Guardar Proyecto',
|
||||
|
||||
'error_mercurial' => 'La URL del repositorio de Mercurial debe comenzar con http:// or https://',
|
||||
'error_remote' => 'La URL del repositorio debe comenzar con git://, http:// or https://',
|
||||
'error_gitlab' => 'El nombre del repositorio de GitLab debe tener el formato "user@domain.tld:owner/repo.git"',
|
||||
'error_github' => 'El nombre del repositorio debe tener el formato "owner/repo"',
|
||||
'error_bitbucket' => 'El nombre del repo debe tener el formato "owner/repo"',
|
||||
'error_path' => 'La ruta especificada no existe.',
|
||||
|
||||
// View Project:
|
||||
'all_branches' => 'Todas las ramas',
|
||||
'builds' => 'Builds',
|
||||
'id' => 'ID',
|
||||
'project' => 'Proyecto',
|
||||
'commit' => 'Commit',
|
||||
'branch' => 'Rama',
|
||||
'status' => 'Estado',
|
||||
'prev_link' => '« Anterior',
|
||||
'next_link' => 'Siguiente »',
|
||||
'public_key' => 'Llave pública',
|
||||
'delete_build' => 'Eliminar Build',
|
||||
|
||||
'webhooks' => 'Webhooks',
|
||||
'webhooks_help_github' => 'Para compilar automáticamente este proyecto cada vez que se realiza un commit, agreagar la siguiente URL
|
||||
como un nuevo "webhook" en la sección <a href="https://github.com/%s/settings/hooks">Webhooks
|
||||
and Services</a> de tu repositorio en GitHub.',
|
||||
|
||||
'webhooks_help_gitlab' => 'Para compilar automáticamente este proyecto, cada vez que se realiza un commit, agreagar la siguiente URL
|
||||
como una "WebHook URL" en la sección "web hooks" de tu repositorio en GitLab.',
|
||||
|
||||
'webhooks_help_bitbucket' => 'Para compilar automáticamente este proyecto, cada vez que se realiza un commit, agreagar la siguiente URL
|
||||
como un servicio "POST" en la sección
|
||||
<a href="https://bitbucket.org/%s/admin/services">
|
||||
Services</a> de tu repositorio en Bitbucket.',
|
||||
|
||||
// View Build
|
||||
'build_x_not_found' => 'El build con ID %d no existe.',
|
||||
'build_n' => 'Build %d',
|
||||
'rebuild_now' => 'Rebuild Ahora',
|
||||
|
||||
|
||||
'committed_by_x' => 'Commit hecho por %s',
|
||||
'commit_id_x' => 'Commit: %s',
|
||||
|
||||
'chart_display' => 'Este gráfico será mostrado una vez que el build se haya completado.',
|
||||
|
||||
'build' => 'Build',
|
||||
'lines' => 'Líneas',
|
||||
'comment_lines' => 'Líneas de comentario',
|
||||
'noncomment_lines' => 'Líneas no comentario',
|
||||
'logical_lines' => 'Líneas lógicas',
|
||||
'lines_of_code' => 'Líneas de código',
|
||||
'build_log' => 'Log',
|
||||
'quality_trend' => 'Tendencia de calidad',
|
||||
'codeception_errors' => 'Errores de Codeception',
|
||||
'phpmd_warnings' => 'PHPMD Warnings',
|
||||
'phpcs_warnings' => 'PHPCS Warnings',
|
||||
'phpcs_errors' => 'PHPCS Errors',
|
||||
'phplint_errors' => 'Lint Errors',
|
||||
'phpunit_errors' => 'PHPUnit Errors',
|
||||
'phpdoccheck_warnings' => 'Docblocks faltantes',
|
||||
'issues' => 'Incidencias',
|
||||
|
||||
'codeception' => 'Codeception',
|
||||
'phpcpd' => 'PHP Copy/Paste Detector',
|
||||
'phpcs' => 'PHP Code Sniffer',
|
||||
'phpdoccheck' => 'Missing Docblocks',
|
||||
'phpmd' => 'PHP Mess Detector',
|
||||
'phpspec' => 'PHP Spec',
|
||||
'phpunit' => 'PHP Unit',
|
||||
'technical_debt' => 'Deuda Técnica',
|
||||
'behat' => 'Behat',
|
||||
|
||||
'file' => 'Archivo',
|
||||
'line' => 'Línea',
|
||||
'class' => 'Clase',
|
||||
'method' => 'Método',
|
||||
'message' => 'Mensaje',
|
||||
'start' => 'Inicio',
|
||||
'end' => 'Fin',
|
||||
'from' => 'De',
|
||||
'to' => 'Para',
|
||||
'suite' => 'Suite',
|
||||
'test' => 'Test',
|
||||
'result' => 'Resultado',
|
||||
'ok' => 'OK',
|
||||
'took_n_seconds' => 'Tomó %d segundos',
|
||||
'build_created' => 'Build Creado',
|
||||
'build_started' => 'Build Comenzado',
|
||||
'build_finished' => 'Build Terminado',
|
||||
|
||||
// Users
|
||||
'name' => 'Nombre',
|
||||
'password_change' => 'Contraseña (dejar en blanco si no quiere cambiarla)',
|
||||
'save' => 'Guardar »',
|
||||
'update_your_details' => 'Actualizar los detalles',
|
||||
'your_details_updated' => 'Tus detalles han sido actualizados.',
|
||||
'add_user' => 'Agregar Usuario',
|
||||
'is_admin' => '¿Es Admin?',
|
||||
'yes' => 'Si',
|
||||
'no' => 'No',
|
||||
'edit' => 'Editar',
|
||||
'edit_user' => 'Editar Usuario',
|
||||
'delete_user' => 'Delete Usuario',
|
||||
'user_n_not_found' => 'Usuario con ID %d no existe.',
|
||||
'is_user_admin' => '¿Es un usuario administrador?',
|
||||
'save_user' => 'Guardar Usuario',
|
||||
|
||||
// Settings:
|
||||
'settings_saved' => 'Tu configuración ha sido guardada.',
|
||||
'settings_check_perms' => 'Tu configuración no fue guardada, verificar los permisos del archivo config.yml.',
|
||||
'settings_cannot_write' => 'PHPCI no puede escribir en el archivo config.yml file, la configuración no será guardada correctamente
|
||||
hasta no corregir esto.',
|
||||
'settings_github_linked' => 'Tu cuenta GitHub ha sido conectada.',
|
||||
'settings_github_not_linked' => 'No se pudo conectar a tu cuenta GitHub.',
|
||||
'build_settings' => 'Configuración del Build ',
|
||||
'github_application' => 'Aplicación GitHub',
|
||||
'github_sign_in' => 'Antes de comenzar a utilizar GitHub, tienes que <a href="%s">ingresar</a> y permitir
|
||||
el acceso a tu cuenta a PHPCI.',
|
||||
'github_phpci_linked' => 'PHPCI ha sido conectado a tu cuenta GitHub.',
|
||||
'github_where_to_find' => 'Donde encontrar estos...',
|
||||
'github_where_help' => 'Si eres priopietario de la aplicaión que quieres usar, puedes encontrar esta información en
|
||||
el área de configuración de <a href="https://github.com/settings/applications">aplicaciones</a>.',
|
||||
|
||||
'email_settings' => 'Configuraciones de Email',
|
||||
'email_settings_help' => 'Para que PHPCI pueda enviar email con el status de los builds,
|
||||
debes configurar las siguientes propiedades SMTP.',
|
||||
|
||||
'application_id' => 'ID de aplicación',
|
||||
'application_secret' => 'Application Secret',
|
||||
|
||||
'smtp_server' => 'Servidor SMTP',
|
||||
'smtp_port' => 'Puerto SMTP',
|
||||
'smtp_username' => 'Usuario SMTP',
|
||||
'smtp_password' => 'Contraseña SMTP',
|
||||
'from_email_address' => 'Dirección de email DE',
|
||||
'default_notification_address' => 'Dirección de correo de notificación por defecto',
|
||||
'use_smtp_encryption' => 'Usar encriptación SMTP?',
|
||||
'none' => 'None',
|
||||
'ssl' => 'SSL',
|
||||
'tls' => 'TLS',
|
||||
|
||||
'failed_after' => 'Considerar el build como fallido luego de ',
|
||||
'5_mins' => '5 Minutos',
|
||||
'15_mins' => '15 Minutos',
|
||||
'30_mins' => '30 Minutos',
|
||||
'1_hour' => '1 Hora',
|
||||
'3_hours' => '3 Horas',
|
||||
|
||||
// Plugins
|
||||
'cannot_update_composer' => 'PHPCI no puede actualizar composer.json porque no tiene permisos de escritura.',
|
||||
'x_has_been_removed' => '%s ha sido elimiando.',
|
||||
'x_has_been_added' => '%s ha sido agregado a composer.json y será instalado la próxima vez que ejecutes composer update.',
|
||||
'enabled_plugins' => 'Activar Plugins',
|
||||
'provided_by_package' => 'Provisto por Paquete',
|
||||
'installed_packages' => 'Paquetes Instalados',
|
||||
'suggested_packages' => 'Paquetes Sugeridos',
|
||||
'title' => 'Título',
|
||||
'description' => 'Descripción',
|
||||
'version' => 'Versión',
|
||||
'install' => 'Instalar »',
|
||||
'remove' => 'Eliminar »',
|
||||
'search_packagist_for_more' => 'Buscar más paquetes en Packagist',
|
||||
'search' => 'Buscar »',
|
||||
|
||||
// Installer
|
||||
'installation_url' => 'URL de la instalación PHPCI',
|
||||
'db_host' => 'Host',
|
||||
'db_name' => 'Nombre de la base de datos',
|
||||
'db_user' => 'Usuario de la base de datos',
|
||||
'db_pass' => 'Clave de la base de datos',
|
||||
'admin_name' => 'Nombre del Admin',
|
||||
'admin_pass' => 'Clave del Admin',
|
||||
'admin_email' => 'Email de Admin',
|
||||
'config_path' => 'Ruta al archivo config',
|
||||
'install_phpci' => 'Instalar PHPCI',
|
||||
'welcome_to_phpci' => 'Bienvenido a PHPCI',
|
||||
'please_answer' => 'Por favor, responde las siguientes preguntas:',
|
||||
'phpci_php_req' => 'PHPCI requiere al menos PHP 5.3.8 para funcionar.',
|
||||
'extension_required' => 'Extensión requerida: %s',
|
||||
'function_required' => 'PHPCI debe poder invocar la función %s(). Está deshabilitada en php.ini?',
|
||||
'requirements_not_met' => 'PHPCI no pudo ser instalado, ya que no se cumplen todos los requerimientos.
|
||||
Por favor, corrige los errores antes de continuar.',
|
||||
'must_be_valid_email' => 'Debe ser una dirección de correos válida.',
|
||||
'must_be_valid_url' => 'Debe ser una URL válida.',
|
||||
'enter_name' => 'Nombre del Admin:',
|
||||
'enter_email' => 'Email del Admin:',
|
||||
'enter_password' => 'Contraseña de Admin:',
|
||||
'enter_phpci_url' => 'La URL de PHPCI ("Por ejemplo: http://phpci.local"): ',
|
||||
|
||||
'enter_db_host' => 'Por favor, ingresa el servidor MySQL [localhost]: ',
|
||||
'enter_db_name' => 'Por favor, ingresa el nombre de la base de datos MySQL [phpci]: ',
|
||||
'enter_db_user' => 'Por favor, ingresa el usuario MySQL [phpci]: ',
|
||||
'enter_db_pass' => 'Por favor, ingresa la contraseña MySQL: ',
|
||||
'could_not_connect' => 'PHPCI no pudo conectarse a MySQL con los datos dados. Por favor, intenta nuevamente.',
|
||||
'setting_up_db' => 'Configurando base de datos... ',
|
||||
'user_created' => '¡Cuenta de usuario creada!',
|
||||
'failed_to_create' => 'PHPCI no pudo crear la cuenta de admin.',
|
||||
'config_exists' => 'El archivo config de PHPCI ya existe y no es vacío.',
|
||||
'update_instead' => 'Si está intentando actualizar PHPCI, por favor, utiliza phpci:update.',
|
||||
|
||||
// Update
|
||||
'update_phpci' => 'Actuliza la base de datos para reflejar los modelos actualizados.',
|
||||
'updating_phpci' => 'Actualizando base de datos PHPCI: ',
|
||||
'not_installed' => 'PHPCI no está instalado.',
|
||||
'install_instead' => 'Por favor, instala PHPCI via phpci:install.',
|
||||
|
||||
// Poll Command
|
||||
'poll_github' => 'Chequear en GitHub si se necesita comenzar un Build.',
|
||||
'no_token' => 'No se encontró ningún token GitHub',
|
||||
'finding_projects' => 'Buscando proyectos para chequear',
|
||||
'found_n_projects' => 'Se encontraron %d proyectos',
|
||||
'last_commit_is' => 'El último commit en GitHub para %s es %s',
|
||||
'adding_new_build' => 'Último commit es diferente a la base de datos, agregando nuevo build.',
|
||||
'finished_processing_builds' => 'Fin de procesamiento de builds.',
|
||||
|
||||
// Create Admin
|
||||
'create_admin_user' => 'Crear un usuario Admin',
|
||||
'incorrect_format' => 'Formato incorrecto',
|
||||
|
||||
// Run Command
|
||||
'run_all_pending' => 'Ejecutar todos los builds PHPCI pendientes.',
|
||||
'finding_builds' => 'Buscando builds a procesar',
|
||||
'found_n_builds' => 'Se encontraron %d builds',
|
||||
'skipping_build' => 'Saltando Build %d - Build del proyecto ya en ejecución.',
|
||||
'marked_as_failed' => 'Build %d falló debido a timeout.',
|
||||
|
||||
// Builder
|
||||
'missing_phpci_yml' => 'Este proyecto no contiene el archivo phpci.yml o está vacío.',
|
||||
'build_success' => 'BUILD EXITOSO',
|
||||
'build_failed' => 'BUILD FALLIDO',
|
||||
'removing_build' => 'Eliminando Build.',
|
||||
'exception' => 'Excepción: ',
|
||||
'could_not_create_working' => 'Imposible crear copia de trabajo.',
|
||||
'working_copy_created' => 'Copia de trabajo creada: %s',
|
||||
'looking_for_binary' => 'Buscando binario: %s',
|
||||
'found_in_path' => 'Encontrado en %s: %s',
|
||||
'running_plugin' => 'EJECUTANDO PLUGIN: %s',
|
||||
'plugin_success' => 'PLUGIN: EXITO',
|
||||
'plugin_failed' => 'PLUGIN: FALLÓ',
|
||||
'plugin_missing' => 'No existe el plugin: %s',
|
||||
'tap_version' => 'TapParser únicamente soporta la verisón 13 de TAP',
|
||||
'tap_error' => 'Cadena de caracteres TAP inválida, el número de tests no coincide con la cuenta de tests declarada.',
|
||||
|
||||
// Build Plugins:
|
||||
'no_tests_performed' => 'No se ejecutaron tests.',
|
||||
'could_not_find' => 'No se encontró %s',
|
||||
'no_campfire_settings' => 'No se especificaron parámetros de conexión para el plugin Campfire',
|
||||
'failed_to_wipe' => 'Imposible eliminar directorio existente %s antes de copiarlo',
|
||||
'passing_build' => 'Build Exitoso',
|
||||
'failing_build' => 'Build Fallido',
|
||||
'log_output' => 'Log de Salida: ',
|
||||
'n_emails_sent' => '%d emails enviados.',
|
||||
'n_emails_failed' => '%d emails no pudieron ser enviados.',
|
||||
'unable_to_set_env' => 'Imposible setear variable de entorno',
|
||||
'tag_created' => 'Tag creado por PHPCI: %s',
|
||||
'x_built_at_x' => 'Build de %PROJECT_TITLE% en %BUILD_URI%',
|
||||
'hipchat_settings' => 'Por favor, definir room y authToken para el plugin hipchat_notify',
|
||||
'irc_settings' => 'Debes configurar un servidor, room y apodo.',
|
||||
'invalid_command' => 'Comando inválido',
|
||||
'import_file_key' => 'Sentencia de importación debe contener una llave \'file\'',
|
||||
'cannot_open_import' => 'Imposible abrir archivo de importación SQL: %s',
|
||||
'unable_to_execute' => 'Imposible ejecutar archivo SQL',
|
||||
'phar_internal_error' => 'Error interno en plugin Phar',
|
||||
'build_file_missing' => 'El archivo de build especificado no existe.',
|
||||
'property_file_missing' => 'El archivo de propiedades especificado no existe.',
|
||||
'could_not_process_report' => 'Imposible procesar el reporte generado por la herramienta.',
|
||||
'shell_not_enabled' => 'El plugin shell no está habilitado. Por favor, habilitalo desde config.yml.'
|
||||
);
|
|
@ -39,6 +39,7 @@ PHPCI',
|
|||
'reset_email_title' => 'Réinitialisation du mot de passe PHPCI pour %s',
|
||||
'reset_invalid' => 'Requête de réinitialisation de mot de passe invalide.',
|
||||
'email_address' => 'Adresse email',
|
||||
'login' => 'Login / Email Address',
|
||||
'password' => 'Mot de passe',
|
||||
'log_in' => 'Connexion',
|
||||
|
||||
|
@ -127,6 +128,7 @@ PHPCI',
|
|||
'all_branches' => 'Toutes les branches',
|
||||
'builds' => 'Builds',
|
||||
'id' => 'ID',
|
||||
'date' => 'Date',
|
||||
'project' => 'Projet',
|
||||
'commit' => 'Commit',
|
||||
'branch' => 'Branche',
|
||||
|
@ -194,14 +196,20 @@ PHPCI',
|
|||
'end' => 'Fin',
|
||||
'from' => 'À partir de',
|
||||
'to' => 'jusque',
|
||||
'suite' => 'Suite',
|
||||
'test' => 'Test',
|
||||
'result' => 'Resultat',
|
||||
'ok' => 'OK',
|
||||
'took_n_seconds' => 'Exécuté en %d secondes',
|
||||
'build_created' => 'Build créé',
|
||||
'build_started' => 'Build démarré',
|
||||
'build_finished' => 'Build terminé',
|
||||
'test_message' => 'Message',
|
||||
'test_no_message' => 'Pas de message',
|
||||
'test_success' => 'Réussi(s): %d',
|
||||
'test_fail' => 'Echec(s): %d',
|
||||
'test_skipped' => 'Passé(s): %d',
|
||||
'test_error' => 'Erreurs: %d',
|
||||
'test_todo' => 'Todos: %d',
|
||||
'test_total' => '%d test(s)',
|
||||
|
||||
// Users
|
||||
'name' => 'Nom',
|
||||
|
@ -264,7 +272,7 @@ PHPCI',
|
|||
// Plugins
|
||||
'cannot_update_composer' => 'PHPCI ne peut pas mettre à jour le fichier composer.json pour vous, il n\'est pas modifiable.',
|
||||
'x_has_been_removed' => '%s a été supprimé.',
|
||||
'x_has_been_added' => '%s a été ajouté au fichier composer.json poru vous et il sera installé la prochaine fois
|
||||
'x_has_been_added' => '%s a été ajouté au fichier composer.json pour vous et il sera installé la prochaine fois
|
||||
que vous lancerez "composer update".',
|
||||
'enabled_plugins' => 'Plugins activés',
|
||||
'provided_by_package' => 'Fournis par le paquet',
|
||||
|
@ -278,6 +286,17 @@ PHPCI',
|
|||
'search_packagist_for_more' => 'Rechercher sur Packagist pour trouver plus de paquets',
|
||||
'search' => 'Rechercher »',
|
||||
|
||||
// Summary plugin
|
||||
'build-summary' => 'Résumé',
|
||||
'stage' => 'Étape',
|
||||
'duration' => 'Durée',
|
||||
'plugin' => 'Plugin',
|
||||
'stage_setup' => 'Préparation',
|
||||
'stage_test' => 'Test',
|
||||
'stage_complete' => 'Terminé',
|
||||
'stage_success' => 'Succes',
|
||||
'stage_failure' => 'Échec',
|
||||
|
||||
// Installer
|
||||
'installation_url' => 'URL d\'installation de PHPCI',
|
||||
'db_host' => 'Hôte de la BDD',
|
||||
|
@ -298,9 +317,9 @@ PHPCI',
|
|||
Merci de corriger les erreurs ci-dessus avant de continuer.',
|
||||
'must_be_valid_email' => 'Doit être une adresse email valide.',
|
||||
'must_be_valid_url' => 'Doit être une URL valide.',
|
||||
'enter_name' => 'Nom de l\'admin :',
|
||||
'enter_email' => 'Email de l\'admin :',
|
||||
'enter_password' => 'Mot de passe de l\'admin :',
|
||||
'enter_name' => 'Nom de l\'admin: ',
|
||||
'enter_email' => 'Email de l\'admin: ',
|
||||
'enter_password' => 'Mot de passe de l\'admin: ',
|
||||
'enter_phpci_url' => 'Votre URL vers PHPCI (par exemple "http://phpci.local"): ',
|
||||
|
||||
'enter_db_host' => 'Merci d\'entrer le nom d\'hôte MySQL [localhost]: ',
|
||||
|
@ -333,6 +352,12 @@ PHPCI',
|
|||
'create_admin_user' => 'Créer un utilisateur admin',
|
||||
'incorrect_format' => 'Format incorrect',
|
||||
|
||||
// Create Build Command
|
||||
'create_build_project' => 'Créer un build projet',
|
||||
'project_id_argument' => 'ID du projet',
|
||||
'commit_id_option' => 'ID du commit',
|
||||
'branch_name_option' => 'Branche',
|
||||
|
||||
// Run Command
|
||||
'run_all_pending' => 'Démarrage de tout les builds PHPCI en attente.',
|
||||
'finding_builds' => 'Découverte des builds à traiter',
|
||||
|
|
|
@ -39,6 +39,7 @@ PHPCI',
|
|||
'reset_email_title' => 'Ripristino della password di PHPCI per %s',
|
||||
'reset_invalid' => 'Richeista di ripristino password non valida.',
|
||||
'email_address' => 'Indirizzo Email',
|
||||
'login' => 'Login / Email Address',
|
||||
'password' => 'Password',
|
||||
'log_in' => 'Accedi',
|
||||
|
||||
|
@ -127,6 +128,7 @@ PHPCI',
|
|||
'all_branches' => 'Tutti i Branche',
|
||||
'builds' => 'Builds',
|
||||
'id' => 'ID',
|
||||
'date' => 'Data',
|
||||
'project' => 'Progetto',
|
||||
'commit' => 'Commit',
|
||||
'branch' => 'Branch',
|
||||
|
@ -196,14 +198,20 @@ PHPCI',
|
|||
'end' => 'Finisci',
|
||||
'from' => 'Da',
|
||||
'to' => 'A',
|
||||
'suite' => 'Suite',
|
||||
'test' => 'Test',
|
||||
'result' => 'Risultati',
|
||||
'ok' => 'OK',
|
||||
'took_n_seconds' => 'Sono stati impiegati %d seconds',
|
||||
'build_created' => 'Build Creata',
|
||||
'build_started' => 'Build Avviata',
|
||||
'build_finished' => 'Build Terminata',
|
||||
'test_message' => 'Message',
|
||||
'test_no_message' => 'No message',
|
||||
'test_success' => 'Succesfull: %d',
|
||||
'test_fail' => 'Failures: %d',
|
||||
'test_skipped' => 'Skipped: %d',
|
||||
'test_error' => 'Errors: %d',
|
||||
'test_todo' => 'Todos: %d',
|
||||
'test_total' => '%d test(s)',
|
||||
|
||||
// Users
|
||||
'name' => 'Nome',
|
||||
|
@ -300,9 +308,9 @@ PHPCI',
|
|||
Per favore controlla gli errori riportati prima di proseguire.',
|
||||
'must_be_valid_email' => 'Deve essere un indirizzo email valido.',
|
||||
'must_be_valid_url' => 'Deve essere un URL valido.',
|
||||
'enter_name' => 'Nome dell\'amministratore:',
|
||||
'enter_email' => 'Email dell\'amministratore:',
|
||||
'enter_password' => 'Password dell\'amministratore:',
|
||||
'enter_name' => 'Nome dell\'amministratore: ',
|
||||
'enter_email' => 'Email dell\'amministratore: ',
|
||||
'enter_password' => 'Password dell\'amministratore: ',
|
||||
'enter_phpci_url' => 'L\'URL di PHPCI ("http://phpci.locale" ad esempio): ',
|
||||
|
||||
'enter_db_host' => 'Per favore inserisci l\'host MySQL [localhost]: ',
|
||||
|
@ -335,6 +343,12 @@ PHPCI',
|
|||
'create_admin_user' => 'Crea un nuovo utente amministrarore',
|
||||
'incorrect_format' => 'Formato errato',
|
||||
|
||||
// Create Build Command
|
||||
'create_build_project' => 'Create a build for a project',
|
||||
'project_id_argument' => 'A project ID',
|
||||
'commit_id_option' => 'Commit ID to build',
|
||||
'branch_name_option' => 'Branch to build',
|
||||
|
||||
// Run Command
|
||||
'run_all_pending' => 'Esegui tutte le build in attesa su PHPCI.',
|
||||
'finding_builds' => 'Ricerca delel build da processare',
|
||||
|
|
|
@ -39,6 +39,7 @@ PHPCI',
|
|||
'reset_email_title' => 'PHPCI wachtwoord reset voor %s',
|
||||
'reset_invalid' => 'Ongeldig wachtwoord reset verzoek',
|
||||
'email_address' => 'E-mailadres',
|
||||
'login' => 'Login / Email Address',
|
||||
'password' => 'Wachtwoord',
|
||||
'log_in' => 'Log in',
|
||||
|
||||
|
@ -127,6 +128,7 @@ van je gekozen source code hosting platform',
|
|||
'all_branches' => 'Alle brances',
|
||||
'builds' => 'Builds',
|
||||
'id' => 'ID',
|
||||
'date' => 'Datum',
|
||||
'project' => 'Project',
|
||||
'commit' => 'Commit',
|
||||
'branch' => 'Branch',
|
||||
|
@ -194,14 +196,20 @@ Services</a> sectie van je Bitbucket repository toegevoegd worden.',
|
|||
'end' => 'Einde',
|
||||
'from' => 'Van',
|
||||
'to' => 'Tot',
|
||||
'suite' => 'Suite',
|
||||
'test' => 'Test',
|
||||
'result' => 'Resultaat',
|
||||
'ok' => 'OK',
|
||||
'took_n_seconds' => 'Duurde %d seconden',
|
||||
'build_created' => 'Build aangemaakt',
|
||||
'build_started' => 'Build gestart',
|
||||
'build_finished' => 'Build beëindigd',
|
||||
'test_message' => 'Message',
|
||||
'test_no_message' => 'No message',
|
||||
'test_success' => 'Succesfull: %d',
|
||||
'test_fail' => 'Failures: %d',
|
||||
'test_skipped' => 'Skipped: %d',
|
||||
'test_error' => 'Errors: %d',
|
||||
'test_todo' => 'Todos: %d',
|
||||
'test_total' => '%d test(s)',
|
||||
|
||||
// Users
|
||||
'name' => 'Naam',
|
||||
|
@ -298,15 +306,15 @@ keer je composer update uitvoert.',
|
|||
Gelieve de fouten na te kijken vooraleer verder te gaan.',
|
||||
'must_be_valid_email' => 'Moet een geldig e-mailadres zijn.',
|
||||
'must_be_valid_url' => 'Moet een geldige URL zijn.',
|
||||
'enter_name' => 'Administrator naam:',
|
||||
'enter_email' => 'Administrator e-mailadres:',
|
||||
'enter_password' => 'Administrator wachtwoord:',
|
||||
'enter_phpci_url' => 'Je PHPCI URL (bijvoorbeeld "http://phpci.local")',
|
||||
'enter_name' => 'Administrator naam: ',
|
||||
'enter_email' => 'Administrator e-mailadres: ',
|
||||
'enter_password' => 'Administrator wachtwoord: ',
|
||||
'enter_phpci_url' => 'Je PHPCI URL (bijvoorbeeld "http://phpci.local"): ',
|
||||
|
||||
'enter_db_host' => 'Vul je MySQL host in [localhost]:',
|
||||
'enter_db_name' => 'Vul je MySQL databasenaam in [phpci]:',
|
||||
'enter_db_user' => 'Vul je MySQL gebruikersnaam in [phpci]:',
|
||||
'enter_db_pass' => 'Vul je MySQL watchtwoord in:',
|
||||
'enter_db_host' => 'Vul je MySQL host in [localhost]: ',
|
||||
'enter_db_name' => 'Vul je MySQL databasenaam in [phpci]: ',
|
||||
'enter_db_user' => 'Vul je MySQL gebruikersnaam in [phpci]: ',
|
||||
'enter_db_pass' => 'Vul je MySQL watchtwoord in: ',
|
||||
'could_not_connect' => 'PHPCI kon met deze gegevens geen verbinding maken met MySQL. Gelieve opnieuw te proberen.',
|
||||
'setting_up_db' => 'Database wordt aangemaakt...',
|
||||
'user_created' => 'Gebruikersprofiel aangemaakt!',
|
||||
|
@ -333,6 +341,12 @@ Gelieve de fouten na te kijken vooraleer verder te gaan.',
|
|||
'create_admin_user' => 'Administrator-gebruiker aanmaken',
|
||||
'incorrect_format' => 'Incorrect formaat',
|
||||
|
||||
// Create Build Command
|
||||
'create_build_project' => 'Create a build for a project',
|
||||
'project_id_argument' => 'A project ID',
|
||||
'commit_id_option' => 'Commit ID to build',
|
||||
'branch_name_option' => 'Branch to build',
|
||||
|
||||
// Run Command
|
||||
'run_all_pending' => 'Voer alle wachtende PHPCI builds uit.',
|
||||
'finding_builds' => 'Zoekt builds om te verwerken',
|
||||
|
|
|
@ -39,6 +39,7 @@ PHPCI',
|
|||
'reset_email_title' => 'Reset Hasła PHPCI dla %s',
|
||||
'reset_invalid' => 'Prośba o zmianę hasła jest nieważna.',
|
||||
'email_address' => 'Adres email',
|
||||
'login' => 'Login / Email Address',
|
||||
'password' => 'Hasło',
|
||||
'log_in' => 'Zaloguj się',
|
||||
|
||||
|
@ -128,6 +129,7 @@ od wybranego kodu źródłowego platformy hostingowej.',
|
|||
'all_branches' => 'Wszystkie Gałęzie',
|
||||
'builds' => 'Budowania',
|
||||
'id' => 'ID',
|
||||
'date' => 'Date',
|
||||
'project' => 'Projekt',
|
||||
'commit' => 'Commit',
|
||||
'branch' => 'Gałąź',
|
||||
|
@ -197,14 +199,20 @@ Services</a> repozytoria Bitbucket.',
|
|||
'end' => 'Koniec',
|
||||
'from' => 'Od',
|
||||
'to' => 'Do',
|
||||
'suite' => 'Zestaw ',
|
||||
'test' => 'Test',
|
||||
'result' => 'Wynik',
|
||||
'ok' => 'OK',
|
||||
'took_n_seconds' => 'Zajęło %d sekund',
|
||||
'build_created' => 'Budowanie Stworzone',
|
||||
'build_started' => 'Budowanie Rozpoczęte',
|
||||
'build_finished' => 'Budowanie Zakończone',
|
||||
'test_message' => 'Message',
|
||||
'test_no_message' => 'No message',
|
||||
'test_success' => 'Succesfull: %d',
|
||||
'test_fail' => 'Failures: %d',
|
||||
'test_skipped' => 'Skipped: %d',
|
||||
'test_error' => 'Errors: %d',
|
||||
'test_todo' => 'Todos: %d',
|
||||
'test_total' => '%d test(s)',
|
||||
|
||||
// Users
|
||||
'name' => 'Nazwa',
|
||||
|
@ -299,15 +307,15 @@ wywołaniu polecenia composer update.',
|
|||
Przejrzyj powyższą listę błędów przed kontynuowaniem.',
|
||||
'must_be_valid_email' => 'Poprawny adres email jest wymagany.',
|
||||
'must_be_valid_url' => 'Poprawny URL jest wymagany.',
|
||||
'enter_name' => 'Imię Admina:',
|
||||
'enter_email' => 'Email Admina:',
|
||||
'enter_password' => 'Hasło Admina:',
|
||||
'enter_phpci_url' => 'URL PHPCI (na przykład "http://phpci.local"):',
|
||||
'enter_name' => 'Imię Admina: ',
|
||||
'enter_email' => 'Email Admina: ',
|
||||
'enter_password' => 'Hasło Admina: ',
|
||||
'enter_phpci_url' => 'URL PHPCI (na przykład "http://phpci.local"): ',
|
||||
|
||||
'enter_db_host' => 'Wpisz hosta MySQL [host lokalny]:',
|
||||
'enter_db_name' => 'Wpisz nazwę bazy danych MySQL [phpci]:',
|
||||
'enter_db_user' => 'Wpisz nazwę użytkownika MySQL [phpci]:',
|
||||
'enter_db_pass' => 'Wpisz hasło MySQL:',
|
||||
'enter_db_host' => 'Wpisz hosta MySQL [host lokalny]: ',
|
||||
'enter_db_name' => 'Wpisz nazwę bazy danych MySQL [phpci]: ',
|
||||
'enter_db_user' => 'Wpisz nazwę użytkownika MySQL [phpci]: ',
|
||||
'enter_db_pass' => 'Wpisz hasło MySQL: ',
|
||||
'could_not_connect' => 'Z podanymi ustawieniami PHPCI nie udało się połączyć z MySQL. Spróbuj ponownie.',
|
||||
'setting_up_db' => 'Ustawianie Twojej bazy danych...',
|
||||
'user_created' => 'Utworzono konto użytkownika!',
|
||||
|
@ -334,6 +342,12 @@ Przejrzyj powyższą listę błędów przed kontynuowaniem.',
|
|||
'create_admin_user' => 'Utwórz admina',
|
||||
'incorrect_format' => 'Niepoprawny format',
|
||||
|
||||
// Create Build Command
|
||||
'create_build_project' => 'Create a build for a project',
|
||||
'project_id_argument' => 'A project ID',
|
||||
'commit_id_option' => 'Commit ID to build',
|
||||
'branch_name_option' => 'Branch to build',
|
||||
|
||||
// Run Command
|
||||
'run_all_pending' => 'Uruchom wszystkie oczekujące budowy w PHPCI',
|
||||
'finding_builds' => 'Szukam budów do przetwarzania.',
|
||||
|
|
|
@ -38,6 +38,7 @@ PHPCI',
|
|||
'reset_email_title' => 'Сброс пароля PHPCI для %s',
|
||||
'reset_invalid' => 'Некорректный запрос на сброс пароля.',
|
||||
'email_address' => 'Email',
|
||||
'login' => 'Логин / Email',
|
||||
'password' => 'Пароль',
|
||||
'log_in' => 'Войти',
|
||||
|
||||
|
@ -112,7 +113,7 @@ PHPCI',
|
|||
(если вы не добавили файл phpci.yml в репозиторий вашего проекта)',
|
||||
'default_branch' => 'Ветка по умолчанию',
|
||||
'allow_public_status' => 'Разрешить публичный статус и изображение (статуса) для проекта',
|
||||
'archived' => 'Archived',
|
||||
'archived' => 'Запакован',
|
||||
'save_project' => 'Сохранить проект',
|
||||
|
||||
'error_mercurial' => 'URL репозитория Mercurial должен начинаться с http:// или https://',
|
||||
|
@ -126,6 +127,7 @@ PHPCI',
|
|||
'all_branches' => 'Все ветки',
|
||||
'builds' => 'Сборки',
|
||||
'id' => 'ID',
|
||||
'date' => 'Дата',
|
||||
'project' => 'Проект',
|
||||
'commit' => 'Коммит',
|
||||
'branch' => 'Ветка',
|
||||
|
@ -188,18 +190,24 @@ PHPCI',
|
|||
'class' => 'Класс',
|
||||
'method' => 'Метод',
|
||||
'message' => 'Сообщение',
|
||||
'start' => 'Запуск',
|
||||
'start' => 'Начало',
|
||||
'end' => 'Конец',
|
||||
'from' => 'От',
|
||||
'to' => 'До',
|
||||
'suite' => 'Комплект',
|
||||
'test' => 'Тест',
|
||||
'from' => 'Из',
|
||||
'to' => 'В',
|
||||
'result' => 'Результат',
|
||||
'ok' => 'OK',
|
||||
'took_n_seconds' => 'Заняло секунд: %d',
|
||||
'build_created' => 'Сборка создана',
|
||||
'build_started' => 'Сборка запущена',
|
||||
'build_finished' => 'Сборка окончена',
|
||||
'test_message' => 'Message',
|
||||
'test_no_message' => 'No message',
|
||||
'test_success' => 'Succesfull: %d',
|
||||
'test_fail' => 'Failures: %d',
|
||||
'test_skipped' => 'Skipped: %d',
|
||||
'test_error' => 'Errors: %d',
|
||||
'test_todo' => 'Todos: %d',
|
||||
'test_total' => '%d test(s)',
|
||||
|
||||
// Users
|
||||
'name' => 'Имя',
|
||||
|
@ -294,9 +302,9 @@ PHPCI',
|
|||
Пожалуйста, просмотрите возникшие ошибки перед тем, как продолжить.',
|
||||
'must_be_valid_email' => 'Должен быть корректным email-адресом.',
|
||||
'must_be_valid_url' => 'Должен быть корректным URL-адресом.',
|
||||
'enter_name' => 'Имя администратора:',
|
||||
'enter_email' => 'Email администратора:',
|
||||
'enter_password' => 'Пароль администратора:',
|
||||
'enter_name' => 'Имя администратора: ',
|
||||
'enter_email' => 'Email администратора: ',
|
||||
'enter_password' => 'Пароль администратора: ',
|
||||
'enter_phpci_url' => 'URL-адрес вашего PHPCI (например: "http://phpci.local"): ',
|
||||
|
||||
'enter_db_host' => 'Пожалуйста, введите хост MySQL [localhost]: ',
|
||||
|
@ -329,6 +337,12 @@ PHPCI',
|
|||
'create_admin_user' => 'Добавить аккаунт администратора',
|
||||
'incorrect_format' => 'Неверный формат',
|
||||
|
||||
// Create Build Command
|
||||
'create_build_project' => 'Создать сборку проекта',
|
||||
'project_id_argument' => 'ID проекта',
|
||||
'commit_id_option' => 'ID коммита для сборки',
|
||||
'branch_name_option' => 'Ветка для сборки',
|
||||
|
||||
// Run Command
|
||||
'run_all_pending' => 'Запустить все ожидающие PHPCI сборки.',
|
||||
'finding_builds' => 'Поиск сборок для запуска',
|
||||
|
|
|
@ -39,6 +39,7 @@ PHPCI',
|
|||
'reset_email_title' => 'Скидання пароль PHPCI для %s',
|
||||
'reset_invalid' => 'Невірний запит скидання паролю.',
|
||||
'email_address' => 'Email адреса',
|
||||
'login' => 'Логин / Email адреса',
|
||||
'password' => 'Пароль',
|
||||
'log_in' => 'Увійти',
|
||||
|
||||
|
@ -126,6 +127,7 @@ PHPCI',
|
|||
'all_branches' => 'Усі гілки',
|
||||
'builds' => 'Збірки',
|
||||
'id' => 'ID',
|
||||
'date' => 'Дата',
|
||||
'project' => 'Проект',
|
||||
'commit' => 'Комміт',
|
||||
'branch' => 'Гілка',
|
||||
|
@ -194,14 +196,20 @@ PHPCI',
|
|||
'end' => 'Кінець',
|
||||
'from' => 'Від',
|
||||
'to' => 'До',
|
||||
'suite' => 'Комплект',
|
||||
'test' => 'Тест',
|
||||
'result' => 'Результат',
|
||||
'ok' => 'OK',
|
||||
'took_n_seconds' => 'Зайняло %d секунд',
|
||||
'build_created' => 'Збірка створена',
|
||||
'build_started' => 'Збірка розпочата',
|
||||
'build_finished' => 'Збірка завершена',
|
||||
'test_message' => 'Message',
|
||||
'test_no_message' => 'No message',
|
||||
'test_success' => 'Succesfull: %d',
|
||||
'test_fail' => 'Failures: %d',
|
||||
'test_skipped' => 'Skipped: %d',
|
||||
'test_error' => 'Errors: %d',
|
||||
'test_todo' => 'Todos: %d',
|
||||
'test_total' => '%d test(s)',
|
||||
|
||||
// Users
|
||||
'name' => 'Ім’я',
|
||||
|
@ -298,15 +306,15 @@ PHPCI',
|
|||
Будь ласка, продивіться наявні помилки перед тим, як продовжити.',
|
||||
'must_be_valid_email' => 'Повинно бути коректною email адресою.',
|
||||
'must_be_valid_url' => 'Повинно бути коректним URL.',
|
||||
'enter_name' => 'Ім’я адміністратора:',
|
||||
'enter_email' => 'Email адміністратора:',
|
||||
'enter_password' => 'Пароль адміністратора:',
|
||||
'enter_phpci_url' => 'URL адреса вашого PHPCI (наприклад, "http://phpci.local"):',
|
||||
'enter_name' => 'Ім’я адміністратора: ',
|
||||
'enter_email' => 'Email адміністратора: ',
|
||||
'enter_password' => 'Пароль адміністратора: ',
|
||||
'enter_phpci_url' => 'URL адреса вашого PHPCI (наприклад, "http://phpci.local"): ',
|
||||
|
||||
'enter_db_host' => 'Будь ласка, введіть хост MySQL [localhost]:',
|
||||
'enter_db_name' => 'Будь ласка, введить ім’я бази даних MySQL [phpci]:',
|
||||
'enter_db_user' => 'Будь ласка, введить ім’я користувача MySQL [phpci]:',
|
||||
'enter_db_pass' => 'Будь ласка, введить ваш пароль MySQL:',
|
||||
'enter_db_host' => 'Будь ласка, введіть хост MySQL [localhost]: ',
|
||||
'enter_db_name' => 'Будь ласка, введить ім’я бази даних MySQL [phpci]: ',
|
||||
'enter_db_user' => 'Будь ласка, введить ім’я користувача MySQL [phpci]: ',
|
||||
'enter_db_pass' => 'Будь ласка, введить ваш пароль MySQL: ',
|
||||
'could_not_connect' => 'PHPCI не може підключитися до MySQL із наданими параметрами. Будь ласка, спробуйте ще раз.',
|
||||
'setting_up_db' => 'Налаштування вашої бази даних...',
|
||||
'user_created' => 'Аккаунт користувача створено!',
|
||||
|
@ -333,6 +341,12 @@ PHPCI',
|
|||
'create_admin_user' => 'Створити аккаунт адміністратора',
|
||||
'incorrect_format' => 'Невірний формат',
|
||||
|
||||
// Create Build Command
|
||||
'create_build_project' => 'Create a build for a project',
|
||||
'project_id_argument' => 'A project ID',
|
||||
'commit_id_option' => 'Commit ID to build',
|
||||
'branch_name_option' => 'Branch to build',
|
||||
|
||||
// Run Command
|
||||
'run_all_pending' => 'Запустити всі PHPCI збірки, які очікують.',
|
||||
'finding_builds' => 'Пошук збірок для обробки',
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
namespace PHPCI\Logging;
|
||||
|
||||
use Monolog\ErrorHandler;
|
||||
use Monolog\Logger;
|
||||
|
||||
/**
|
||||
|
@ -19,6 +20,7 @@ class LoggerConfig
|
|||
{
|
||||
const KEY_ALWAYS_LOADED = "_";
|
||||
private $config;
|
||||
private $cache = array();
|
||||
|
||||
/**
|
||||
* The filepath is expected to return an array which will be
|
||||
|
@ -56,9 +58,20 @@ class LoggerConfig
|
|||
*/
|
||||
public function getFor($name)
|
||||
{
|
||||
if (isset($this->cache[$name])) {
|
||||
return $this->cache[$name];
|
||||
}
|
||||
|
||||
$handlers = $this->getHandlers(self::KEY_ALWAYS_LOADED);
|
||||
$handlers = array_merge($handlers, $this->getHandlers($name));
|
||||
return new Logger($name, $handlers);
|
||||
if ($name !== self::KEY_ALWAYS_LOADED) {
|
||||
$handlers = array_merge($handlers, $this->getHandlers($name));
|
||||
}
|
||||
|
||||
$logger = new Logger($name, $handlers);
|
||||
ErrorHandler::register($logger);
|
||||
$this->cache[$name] = $logger;
|
||||
|
||||
return $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
use Phinx\Migration\AbstractMigration;
|
||||
|
||||
class UniqueEmailAndNameUserFields extends AbstractMigration
|
||||
{
|
||||
/**
|
||||
* Migrate Up.
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
$user_table = $this->table('user');
|
||||
$user_table
|
||||
->addIndex('email', array('unique' => true))
|
||||
->addIndex('name', array('unique' => true))
|
||||
->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Migrate Down.
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
$user_table = $this->table('user');
|
||||
$user_table
|
||||
->removeIndex('email', array('unique' => true))
|
||||
->removeIndex('name', array('unique' => true))
|
||||
->save();
|
||||
}
|
||||
}
|
|
@ -217,4 +217,31 @@ class Build extends BuildBase
|
|||
{
|
||||
return array($builder, $file, $line, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the path to run this build into.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getBuildPath()
|
||||
{
|
||||
if (!$this->getId()) {
|
||||
return null;
|
||||
}
|
||||
return PHPCI_BUILD_ROOT_DIR . $this->getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the build directory.
|
||||
*/
|
||||
public function removeBuildDirectory()
|
||||
{
|
||||
$buildPath = $this->getBuildPath();
|
||||
|
||||
if (!$buildPath || !is_dir($buildPath)) {
|
||||
return;
|
||||
}
|
||||
|
||||
exec(sprintf(IS_WIN ? 'rmdir /S /Q "%s"' : 'rm -Rf "%s"', $buildPath));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -125,7 +125,7 @@ class GithubBuild extends RemoteGitBuild
|
|||
|
||||
if ($this->getExtra('build_type') == 'pull_request') {
|
||||
$matches = array();
|
||||
preg_match('/\/([a-zA-Z0-9_\-]+\/[a-zA-Z0-9_\-]+)/', $this->getExtra('remote_url'), $matches);
|
||||
preg_match('/[\/:]([a-zA-Z0-9_\-]+\/[a-zA-Z0-9_\-]+)/', $this->getExtra('remote_url'), $matches);
|
||||
|
||||
$reference = $matches[1];
|
||||
$branch = $this->getExtra('remote_branch');
|
||||
|
|
|
@ -47,7 +47,7 @@ class GitlabBuild extends RemoteGitBuild
|
|||
'http://%s/%s/blob/%s/{FILE}#L{LINE}',
|
||||
$this->getProject()->getAccessInformation("domain"),
|
||||
$this->getProject()->getReference(),
|
||||
$this->getBranch()
|
||||
$this->getCommitId()
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ class RemoteGitBuild extends Build
|
|||
*/
|
||||
protected function cloneByHttp(Builder $builder, $cloneTo)
|
||||
{
|
||||
$cmd = 'git clone ';
|
||||
$cmd = 'git clone --recursive ';
|
||||
|
||||
$depth = $builder->getConfig('clone_depth');
|
||||
|
||||
|
@ -84,7 +84,7 @@ class RemoteGitBuild extends Build
|
|||
}
|
||||
|
||||
// Do the git clone:
|
||||
$cmd = 'git clone ';
|
||||
$cmd = 'git clone --recursive ';
|
||||
|
||||
$depth = $builder->getConfig('clone_depth');
|
||||
|
||||
|
@ -124,16 +124,16 @@ class RemoteGitBuild extends Build
|
|||
$success = true;
|
||||
$commit = $this->getCommitId();
|
||||
|
||||
$chdir = IS_WIN ? 'cd /d "%s"' : 'cd "%s"';
|
||||
|
||||
if (!empty($commit) && $commit != 'Manual') {
|
||||
$cmd = 'cd "%s"';
|
||||
$cmd = $chdir . ' && git checkout %s --quiet';
|
||||
$success = $builder->executeCommand($cmd, $cloneTo, $commit);
|
||||
}
|
||||
|
||||
if (IS_WIN) {
|
||||
$cmd = 'cd /d "%s"';
|
||||
}
|
||||
|
||||
$cmd .= ' && git checkout %s --quiet';
|
||||
|
||||
$success = $builder->executeCommand($cmd, $cloneTo, $this->getCommitId());
|
||||
// Always update the commit hash with the actual HEAD hash
|
||||
if ($builder->executeCommand($chdir . ' && git rev-parse HEAD', $cloneTo)) {
|
||||
$this->setCommitId(trim($builder->getLastOutput()));
|
||||
}
|
||||
|
||||
return $success;
|
||||
|
|
|
@ -98,7 +98,6 @@ class Behat implements \PHPCI\Plugin
|
|||
|
||||
$lines = explode(PHP_EOL, $parts[1]);
|
||||
|
||||
$errorCount = 0;
|
||||
$storeFailures = false;
|
||||
$data = array();
|
||||
|
||||
|
|
|
@ -9,50 +9,72 @@
|
|||
|
||||
namespace PHPCI\Plugin;
|
||||
|
||||
use PHPCI;
|
||||
use PHPCI\Builder;
|
||||
use PHPCI\Helper\Lang;
|
||||
use PHPCI\Model\Build;
|
||||
use PHPCI\Plugin\Util\TapParser;
|
||||
use PHPCI\Plugin\Util\TestResultParsers\Codeception as Parser;
|
||||
use Psr\Log\LogLevel;
|
||||
|
||||
/**
|
||||
* Codeception Plugin - Enables full acceptance, unit, and functional testing
|
||||
*
|
||||
* Codeception Plugin - Enables full acceptance, unit, and functional testing.
|
||||
* @author Don Gilbert <don@dongilbert.net>
|
||||
* @author Igor Timoshenko <contact@igortimoshenko.com>
|
||||
* @author Adam Cooper <adam@networkpie.co.uk>
|
||||
* @package PHPCI
|
||||
* @subpackage Plugins
|
||||
*/
|
||||
class Codeception implements PHPCI\Plugin, PHPCI\ZeroConfigPlugin
|
||||
class Codeception implements \PHPCI\Plugin, \PHPCI\ZeroConfigPlugin
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
/** @var string */
|
||||
protected $args = '';
|
||||
|
||||
/**
|
||||
* @var Build
|
||||
*/
|
||||
/** @var Builder */
|
||||
protected $phpci;
|
||||
|
||||
/** @var Build */
|
||||
protected $build;
|
||||
|
||||
/**
|
||||
* @var Builder
|
||||
* @var string $ymlConfigFile The path of a yml config for Codeception
|
||||
*/
|
||||
protected $phpci;
|
||||
protected $ymlConfigFile;
|
||||
|
||||
/**
|
||||
* @var string|string[] The path (or array of paths) of an yml config for Codeception
|
||||
* @var string $path The path to the codeception tests folder.
|
||||
*/
|
||||
protected $configFile;
|
||||
protected $path;
|
||||
|
||||
/**
|
||||
* @var string The path where the reports and logs are stored
|
||||
* @param $stage
|
||||
* @param Builder $builder
|
||||
* @param Build $build
|
||||
* @return bool
|
||||
*/
|
||||
protected $logPath = 'tests/_output';
|
||||
public static function canExecute($stage, Builder $builder, Build $build)
|
||||
{
|
||||
return $stage == 'test' && !is_null(self::findConfigFile($builder->buildPath));
|
||||
}
|
||||
|
||||
/**
|
||||
* Try and find the codeception YML config file.
|
||||
* @param $buildPath
|
||||
* @return null|string
|
||||
*/
|
||||
public static function findConfigFile($buildPath)
|
||||
{
|
||||
if (file_exists($buildPath . 'codeception.yml')) {
|
||||
return 'codeception.yml';
|
||||
}
|
||||
|
||||
if (file_exists($buildPath . 'codeception.dist.yml')) {
|
||||
return 'codeception.dist.yml';
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up the plugin, configure options, etc.
|
||||
*
|
||||
* @param Builder $phpci
|
||||
* @param Build $build
|
||||
* @param array $options
|
||||
|
@ -61,110 +83,83 @@ class Codeception implements PHPCI\Plugin, PHPCI\ZeroConfigPlugin
|
|||
{
|
||||
$this->phpci = $phpci;
|
||||
$this->build = $build;
|
||||
$this->path = 'tests/_output/';
|
||||
|
||||
if (isset($options['config'])) {
|
||||
$this->configFile = $options['config'];
|
||||
if (empty($options['config'])) {
|
||||
$this->ymlConfigFile = self::findConfigFile($this->phpci->buildPath);
|
||||
} else {
|
||||
$this->ymlConfigFile = $options['config'];
|
||||
}
|
||||
|
||||
if (isset($options['args'])) {
|
||||
$this->args = (string) $options['args'];
|
||||
}
|
||||
|
||||
if (isset($options['log_path'])) {
|
||||
$this->logPath = $options['log_path'];
|
||||
if (isset($options['path'])) {
|
||||
$this->path = $options['path'];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* Runs Codeception tests, optionally using specified config file(s).
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
$success = true;
|
||||
if (empty($this->ymlConfigFile)) {
|
||||
throw new \Exception("No configuration file found");
|
||||
}
|
||||
|
||||
// Run any config files first. This can be either a single value or an array.
|
||||
return $this->runConfigFile($this->ymlConfigFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run tests from a Codeception config file.
|
||||
* @param $configPath
|
||||
* @return bool|mixed
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function runConfigFile($configPath)
|
||||
{
|
||||
$this->phpci->logExecOutput(false);
|
||||
|
||||
// Run any config files first. This can be either a single value or an array
|
||||
if ($this->configFile !== null) {
|
||||
$success &= $this->runConfigFile($this->configFile);
|
||||
$codecept = $this->phpci->findBinary('codecept');
|
||||
|
||||
if (!$codecept) {
|
||||
$this->phpci->logFailure(Lang::get('could_not_find', 'codecept'));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$tapString = file_get_contents(
|
||||
$this->phpci->buildPath . $this->logPath . DIRECTORY_SEPARATOR . 'report.tap.log'
|
||||
$cmd = 'cd "%s" && ' . $codecept . ' run -c "%s" --xml ' . $this->args;
|
||||
if (IS_WIN) {
|
||||
$cmd = 'cd /d "%s" && ' . $codecept . ' run -c "%s" --xml ' . $this->args;
|
||||
}
|
||||
|
||||
$configPath = $this->phpci->buildPath . $configPath;
|
||||
$success = $this->phpci->executeCommand($cmd, $this->phpci->buildPath, $configPath);
|
||||
|
||||
|
||||
$this->phpci->log(
|
||||
'Codeception XML path: '. $this->phpci->buildPath . $this->path . 'report.xml',
|
||||
Loglevel::DEBUG
|
||||
);
|
||||
$xml = file_get_contents($this->phpci->buildPath . $this->path . 'report.xml', false);
|
||||
|
||||
|
||||
$parser = new Parser($this->phpci, $xml);
|
||||
$output = $parser->parse();
|
||||
|
||||
$meta = array(
|
||||
'tests' => $parser->getTotalTests(),
|
||||
'timetaken' => $parser->getTotalTimeTaken(),
|
||||
'failures' => $parser->getTotalFailures()
|
||||
);
|
||||
|
||||
try {
|
||||
$tapParser = new TapParser($tapString);
|
||||
$output = $tapParser->parse();
|
||||
} catch (\Exception $ex) {
|
||||
$this->phpci->logFailure($tapString);
|
||||
|
||||
throw $ex;
|
||||
}
|
||||
|
||||
$failures = $tapParser->getTotalFailures();
|
||||
|
||||
$this->build->storeMeta('codeception-errors', $failures);
|
||||
$this->build->storeMeta('codeception-meta', $meta);
|
||||
$this->build->storeMeta('codeception-data', $output);
|
||||
$this->build->storeMeta('codeception-errors', $parser->getTotalFailures());
|
||||
|
||||
$this->phpci->logExecOutput(true);
|
||||
|
||||
return $success;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public static function canExecute($stage, Builder $builder, Build $build)
|
||||
{
|
||||
return $stage === 'test';
|
||||
}
|
||||
|
||||
/**
|
||||
* Run tests from a Codeception config file
|
||||
*
|
||||
* @param string $configPath
|
||||
* @return bool|mixed
|
||||
*/
|
||||
protected function runConfigFile($configPath)
|
||||
{
|
||||
if (is_array($configPath)) {
|
||||
return $this->recurseArg($configPath, array($this, 'runConfigFile'));
|
||||
} else {
|
||||
$codecept = $this->phpci->findBinary('codecept');
|
||||
|
||||
if (!$codecept) {
|
||||
$this->phpci->logFailure(Lang::get('could_not_find', 'codecept'));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$cmd = 'cd "%s" && ' . $codecept . ' run -c "%s" --tap ' . $this->args;
|
||||
|
||||
if (IS_WIN) {
|
||||
$cmd = 'cd /d "%s" && ' . $codecept . ' run -c "%s" --tap ' . $this->args;
|
||||
}
|
||||
|
||||
$configPath = $this->phpci->buildPath . $configPath;
|
||||
$success = $this->phpci->executeCommand($cmd, $this->phpci->buildPath, $configPath);
|
||||
|
||||
return $success;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $array
|
||||
* @param \Callback $callable
|
||||
* @return bool|mixed
|
||||
*/
|
||||
protected function recurseArg(array $array, $callable)
|
||||
{
|
||||
$success = true;
|
||||
|
||||
foreach ($array as $subItem) {
|
||||
$success &= call_user_func($callable, $subItem);
|
||||
}
|
||||
|
||||
return $success;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ class Composer implements PHPCI\Plugin, PHPCI\ZeroConfigPlugin
|
|||
protected $preferDist;
|
||||
protected $phpci;
|
||||
protected $build;
|
||||
protected $nodev;
|
||||
|
||||
/**
|
||||
* Check if this plugin can be executed.
|
||||
|
@ -60,6 +61,7 @@ class Composer implements PHPCI\Plugin, PHPCI\ZeroConfigPlugin
|
|||
$this->directory = $path;
|
||||
$this->action = 'install';
|
||||
$this->preferDist = false;
|
||||
$this->nodev = false;
|
||||
|
||||
if (array_key_exists('directory', $options)) {
|
||||
$this->directory = $path . '/' . $options['directory'];
|
||||
|
@ -72,6 +74,10 @@ class Composer implements PHPCI\Plugin, PHPCI\ZeroConfigPlugin
|
|||
if (array_key_exists('prefer_dist', $options)) {
|
||||
$this->preferDist = (bool)$options['prefer_dist'];
|
||||
}
|
||||
|
||||
if (array_key_exists('no_dev', $options)) {
|
||||
$this->nodev = (bool)$options['no_dev'];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -81,11 +87,6 @@ class Composer implements PHPCI\Plugin, PHPCI\ZeroConfigPlugin
|
|||
{
|
||||
$composerLocation = $this->phpci->findBinary(array('composer', 'composer.phar'));
|
||||
|
||||
if (!$composerLocation) {
|
||||
$this->phpci->logFailure(Lang::get('could_not_find', 'composer'));
|
||||
return false;
|
||||
}
|
||||
|
||||
$cmd = '';
|
||||
|
||||
if (IS_WIN) {
|
||||
|
@ -102,6 +103,11 @@ class Composer implements PHPCI\Plugin, PHPCI\ZeroConfigPlugin
|
|||
$cmd .= '--prefer-source';
|
||||
}
|
||||
|
||||
if ($this->nodev) {
|
||||
$this->phpci->log('Using --no-dev flag');
|
||||
$cmd .= ' --no-dev';
|
||||
}
|
||||
|
||||
$cmd .= ' --working-dir="%s" %s';
|
||||
|
||||
return $this->phpci->executeCommand($cmd, $this->directory, $this->action);
|
||||
|
|
|
@ -9,11 +9,13 @@
|
|||
|
||||
namespace PHPCI\Plugin;
|
||||
|
||||
use Exception;
|
||||
use b8\View;
|
||||
use PHPCI\Builder;
|
||||
use PHPCI\Helper\Lang;
|
||||
use PHPCI\Model\Build;
|
||||
use PHPCI\Helper\Email as EmailHelper;
|
||||
use Psr\Log\LogLevel;
|
||||
|
||||
/**
|
||||
* Email Plugin - Provides simple email capability to PHPCI.
|
||||
|
@ -70,12 +72,25 @@ class Email implements \PHPCI\Plugin
|
|||
|
||||
$buildStatus = $this->build->isSuccessful() ? "Passing Build" : "Failing Build";
|
||||
$projectName = $this->build->getProject()->getTitle();
|
||||
$mailTemplate = $this->build->isSuccessful() ? 'Email/success' : 'Email/failed';
|
||||
|
||||
$view = new View($mailTemplate);
|
||||
try {
|
||||
$view = $this->getMailTemplate();
|
||||
} catch (Exception $e) {
|
||||
$this->phpci->log(
|
||||
sprintf('Unknown mail template "%s", falling back to default.', $this->options['template']),
|
||||
LogLevel::WARNING
|
||||
);
|
||||
$view = $this->getDefaultMailTemplate();
|
||||
}
|
||||
|
||||
$view->build = $this->build;
|
||||
$view->project = $this->build->getProject();
|
||||
$body = $view->render();
|
||||
|
||||
$layout = new View('Email/layout');
|
||||
$layout->build = $this->build;
|
||||
$layout->project = $this->build->getProject();
|
||||
$layout->content = $view->render();
|
||||
$body = $layout->render();
|
||||
|
||||
$sendFailures = $this->sendSeparateEmails(
|
||||
$addresses,
|
||||
|
@ -97,7 +112,7 @@ class Email implements \PHPCI\Plugin
|
|||
* @param string $body Email body
|
||||
* @return array Array of failed addresses
|
||||
*/
|
||||
public function sendEmail($toAddress, $ccList, $subject, $body)
|
||||
protected function sendEmail($toAddress, $ccList, $subject, $body)
|
||||
{
|
||||
$email = new EmailHelper();
|
||||
|
||||
|
@ -168,6 +183,7 @@ class Email implements \PHPCI\Plugin
|
|||
|
||||
/**
|
||||
* Get the list of email addresses to CC.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getCcAddresses()
|
||||
|
@ -182,4 +198,30 @@ class Email implements \PHPCI\Plugin
|
|||
|
||||
return $ccAddresses;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mail template used to sent the mail.
|
||||
*
|
||||
* @return View
|
||||
*/
|
||||
protected function getMailTemplate()
|
||||
{
|
||||
if (isset($this->options['template'])) {
|
||||
return new View('Email/' . $this->options['template']);
|
||||
}
|
||||
|
||||
return $this->getDefaultMailTemplate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default mail template.
|
||||
*
|
||||
* @return View
|
||||
*/
|
||||
protected function getDefaultMailTemplate()
|
||||
{
|
||||
$template = $this->build->isSuccessful() ? 'short' : 'long';
|
||||
|
||||
return new View('Email/' . $template);
|
||||
}
|
||||
}
|
||||
|
|
73
PHPCI/Plugin/FlowdockNotify.php
Normal file
73
PHPCI/Plugin/FlowdockNotify.php
Normal file
|
@ -0,0 +1,73 @@
|
|||
<?php
|
||||
/**
|
||||
* 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/
|
||||
*/
|
||||
|
||||
namespace PHPCI\Plugin;
|
||||
|
||||
use PHPCI\Builder;
|
||||
use PHPCI\Model\Build;
|
||||
use Mremi\Flowdock\Api\Push\Push;
|
||||
use Mremi\Flowdock\Api\Push\TeamInboxMessage;
|
||||
|
||||
/**
|
||||
* Flowdock Plugin
|
||||
* @author Petr Cervenka <petr@nanosolutions.io>
|
||||
* @package PHPCI
|
||||
* @subpackage Plugins
|
||||
*/
|
||||
class FlowdockNotify implements \PHPCI\Plugin
|
||||
{
|
||||
private $api_key;
|
||||
private $email;
|
||||
const MESSAGE_DEFAULT = 'Build %BUILD% has finished for commit <a href="%COMMIT_URI%">%SHORT_COMMIT%</a>
|
||||
(%COMMIT_EMAIL%)> on branch <a href="%BRANCH_URI%">%BRANCH%</a>';
|
||||
|
||||
/**
|
||||
* Set up the plugin, configure options, etc.
|
||||
* @param Builder $phpci
|
||||
* @param Build $build
|
||||
* @param array $options
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function __construct(Builder $phpci, Build $build, array $options = array())
|
||||
{
|
||||
$this->phpci = $phpci;
|
||||
$this->build = $build;
|
||||
if (!is_array($options) || !isset($options['api_key'])) {
|
||||
throw new \Exception('Please define the api_key for Flowdock Notify plugin!');
|
||||
}
|
||||
$this->api_key = trim($options['api_key']);
|
||||
$this->message = isset($options['message']) ? $options['message'] : self::MESSAGE_DEFAULT;
|
||||
$this->email = isset($options['email']) ? $options['email'] : 'PHPCI';
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the Flowdock plugin.
|
||||
* @return bool
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
|
||||
$message = $this->phpci->interpolate($this->message);
|
||||
$successfulBuild = $this->build->isSuccessful() ? 'Success' : 'Failed';
|
||||
$push = new Push($this->api_key);
|
||||
$flowMessage = TeamInboxMessage::create()
|
||||
->setSource("PHPCI")
|
||||
->setFromAddress($this->email)
|
||||
->setFromName($this->build->getProject()->getTitle())
|
||||
->setSubject($successfulBuild)
|
||||
->setTags(['#ci'])
|
||||
->setLink($this->build->getBranchLink())
|
||||
->setContent($message);
|
||||
|
||||
if (!$push->sendTeamInboxMessage($flowMessage, array('connect_timeout' => 5000, 'timeout' => 5000))) {
|
||||
throw new \Exception(sprintf('Flowdock Failed: %s', $flowMessage->getResponseErrors()));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -77,19 +77,56 @@ class Irc implements \PHPCI\Plugin
|
|||
}
|
||||
|
||||
$sock = fsockopen($this->server, $this->port);
|
||||
fputs($sock, 'USER ' . $this->nick . ' phptesting.org ' . $this->nick . ' :' . $this->nick . "\r\n");
|
||||
fputs($sock, 'NICK ' . $this->nick . "\r\n");
|
||||
fputs($sock, 'JOIN ' . $this->room . "\r\n");
|
||||
fputs($sock, 'PRIVMSG ' . $this->room . ' :' . $msg . "\r\n");
|
||||
stream_set_timeout($sock, 1);
|
||||
|
||||
while (fgets($sock)) {
|
||||
// We don't need to do anything,
|
||||
// but the IRC server doesn't appear to post the message
|
||||
// unless we wait for responses.
|
||||
}
|
||||
$connectCommands = array(
|
||||
'USER ' . $this->nick . ' 0 * :' . $this->nick,
|
||||
'NICK ' . $this->nick,
|
||||
);
|
||||
$this->executeIrcCommands($sock, $connectCommands);
|
||||
$this->executeIrcCommand($sock, 'JOIN ' . $this->room);
|
||||
$this->executeIrcCommand($sock, 'PRIVMSG ' . $this->room . ' :' . $msg);
|
||||
|
||||
fclose($sock);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param resource $socket
|
||||
* @param array $commands
|
||||
* @return bool
|
||||
*/
|
||||
private function executeIrcCommands($socket, array $commands)
|
||||
{
|
||||
foreach ($commands as $command) {
|
||||
fputs($socket, $command . "\n");
|
||||
}
|
||||
|
||||
$pingBack = false;
|
||||
|
||||
// almost all servers expect pingback!
|
||||
while ($response = fgets($socket)) {
|
||||
$matches = array();
|
||||
if (preg_match('/^PING \\:([A-Z0-9]+)/', $response, $matches)) {
|
||||
$pingBack = $matches[1];
|
||||
}
|
||||
}
|
||||
|
||||
if ($pingBack) {
|
||||
$command = 'PONG :' . $pingBack . "\n";
|
||||
fputs($socket, $command);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param resource $socket
|
||||
* @param string $command
|
||||
* @return bool
|
||||
*/
|
||||
private function executeIrcCommand($socket, $command)
|
||||
{
|
||||
return $this->executeIrcCommands($socket, array($command));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -79,15 +79,10 @@ class Pdepend implements \PHPCI\Plugin
|
|||
|
||||
$pdepend = $this->phpci->findBinary('pdepend');
|
||||
|
||||
if (!$pdepend) {
|
||||
$this->phpci->logFailure(Lang::get('could_not_find', 'pdepend'));
|
||||
return false;
|
||||
}
|
||||
|
||||
$cmd = $pdepend . ' --summary-xml="%s" --jdepend-chart="%s" --overview-pyramid="%s" %s "%s"';
|
||||
|
||||
$this->removeBuildArtifacts();
|
||||
|
||||
|
||||
// If we need to ignore directories
|
||||
if (count($this->phpci->ignore)) {
|
||||
$ignore = ' --ignore=' . implode(',', $this->phpci->ignore);
|
||||
|
|
|
@ -81,11 +81,6 @@ class Phing implements \PHPCI\Plugin
|
|||
{
|
||||
$phingExecutable = $this->phpci->findBinary('phing');
|
||||
|
||||
if (!$phingExecutable) {
|
||||
$this->phpci->logFailure(Lang::get('could_not_find', 'phing'));
|
||||
return false;
|
||||
}
|
||||
|
||||
$cmd[] = $phingExecutable . ' -f ' . $this->getBuildFilePath();
|
||||
|
||||
if ($this->getPropertyFile()) {
|
||||
|
|
|
@ -149,11 +149,6 @@ class PhpCodeSniffer implements PHPCI\Plugin, PHPCI\ZeroConfigPlugin
|
|||
|
||||
$phpcs = $this->phpci->findBinary('phpcs');
|
||||
|
||||
if (!$phpcs) {
|
||||
$this->phpci->logFailure(PHPCI\Helper\Lang::get('could_not_find', 'phpcs'));
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->phpci->logExecOutput(false);
|
||||
|
||||
$cmd = $phpcs . ' --report=json %s %s %s %s %s "%s"';
|
||||
|
|
|
@ -90,18 +90,13 @@ class PhpCpd implements \PHPCI\Plugin
|
|||
|
||||
$phpcpd = $this->phpci->findBinary('phpcpd');
|
||||
|
||||
if (!$phpcpd) {
|
||||
$this->phpci->logFailure(Lang::get('could_not_find', 'phpcpd'));
|
||||
return false;
|
||||
}
|
||||
|
||||
$tmpfilename = tempnam('/tmp', 'phpcpd');
|
||||
|
||||
$cmd = $phpcpd . ' --log-pmd "%s" %s "%s"';
|
||||
$success = $this->phpci->executeCommand($cmd, $tmpfilename, $ignore, $this->path);
|
||||
|
||||
print $this->phpci->getLastOutput();
|
||||
|
||||
|
||||
list($errorCount, $data) = $this->processReport(file_get_contents($tmpfilename));
|
||||
$this->build->storeMeta('phpcpd-warnings', $errorCount);
|
||||
$this->build->storeMeta('phpcpd-data', $data);
|
||||
|
|
|
@ -69,11 +69,6 @@ class PhpCsFixer implements \PHPCI\Plugin
|
|||
|
||||
$phpcsfixer = $this->phpci->findBinary('php-cs-fixer');
|
||||
|
||||
if (!$phpcsfixer) {
|
||||
$this->phpci->logFailure(Lang::get('could_not_find', 'php-cs-fixer'));
|
||||
return false;
|
||||
}
|
||||
|
||||
$cmd = $phpcsfixer . ' fix . %s %s %s';
|
||||
$success = $this->phpci->executeCommand($cmd, $this->verbose, $this->diff, $this->level);
|
||||
|
||||
|
|
|
@ -104,11 +104,6 @@ class PhpDocblockChecker implements PHPCI\Plugin, PHPCI\ZeroConfigPlugin
|
|||
// Check that the binary exists:
|
||||
$checker = $this->phpci->findBinary('phpdoccheck');
|
||||
|
||||
if (!$checker) {
|
||||
$this->phpci->logFailure(PHPCI\Helper\Lang::get('could_not_find', 'phpdoccheck'));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Build ignore string:
|
||||
$ignore = '';
|
||||
if (count($this->ignore)) {
|
||||
|
|
|
@ -80,11 +80,6 @@ class PhpLoc implements PHPCI\Plugin, PHPCI\ZeroConfigPlugin
|
|||
|
||||
$phploc = $this->phpci->findBinary('phploc');
|
||||
|
||||
if (!$phploc) {
|
||||
$this->phpci->logFailure(PHPCI\Helper\Lang::get('could_not_find', 'phploc'));
|
||||
return false;
|
||||
}
|
||||
|
||||
$success = $this->phpci->executeCommand($phploc . ' %s "%s"', $ignore, $this->directory);
|
||||
$output = $this->phpci->getLastOutput();
|
||||
|
||||
|
|
|
@ -121,11 +121,6 @@ class PhpMessDetector implements PHPCI\Plugin, PHPCI\ZeroConfigPlugin
|
|||
|
||||
$phpmdBinaryPath = $this->phpci->findBinary('phpmd');
|
||||
|
||||
if (!$phpmdBinaryPath) {
|
||||
$this->phpci->logFailure(PHPCI\Helper\Lang::get('could_not_find', 'phpmd'));
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->executePhpMd($phpmdBinaryPath);
|
||||
|
||||
list($errorCount, $data) = $this->processReport(trim($this->phpci->getLastOutput()));
|
||||
|
|
|
@ -78,11 +78,6 @@ class PhpParallelLint implements \PHPCI\Plugin
|
|||
|
||||
$phplint = $this->phpci->findBinary('parallel-lint');
|
||||
|
||||
if (!$phplint) {
|
||||
$this->phpci->logFailure(Lang::get('could_not_find', 'parallel-lint'));
|
||||
return false;
|
||||
}
|
||||
|
||||
$cmd = $phplint . ' %s "%s"';
|
||||
$success = $this->phpci->executeCommand(
|
||||
$cmd,
|
||||
|
|
|
@ -59,11 +59,6 @@ class PhpSpec implements PHPCI\Plugin
|
|||
|
||||
$phpspec = $this->phpci->findBinary(array('phpspec', 'phpspec.php'));
|
||||
|
||||
if (!$phpspec) {
|
||||
$this->phpci->logFailure(PHPCI\Helper\Lang::get('could_not_find', 'phpspec'));
|
||||
return false;
|
||||
}
|
||||
|
||||
$success = $this->phpci->executeCommand($phpspec . ' --format=junit --no-code-generation run');
|
||||
$output = $this->phpci->getLastOutput();
|
||||
|
||||
|
|
|
@ -197,15 +197,8 @@ class PhpUnit implements PHPCI\Plugin, PHPCI\ZeroConfigPlugin
|
|||
chdir($this->phpci->buildPath.'/'.$this->runFrom);
|
||||
}
|
||||
|
||||
|
||||
$phpunit = $this->phpci->findBinary('phpunit');
|
||||
|
||||
if (!$phpunit) {
|
||||
$this->phpci->logFailure(PHPCI\Helper\Lang::get('could_not_find', 'phpunit'));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
$cmd = $phpunit . ' --tap %s -c "%s" ' . $this->coverage . $this->path;
|
||||
$success = $this->phpci->executeCommand($cmd, $this->args, $this->phpci->buildPath . $configPath);
|
||||
|
||||
|
@ -232,11 +225,6 @@ class PhpUnit implements PHPCI\Plugin, PHPCI\ZeroConfigPlugin
|
|||
|
||||
$phpunit = $this->phpci->findBinary('phpunit');
|
||||
|
||||
if (!$phpunit) {
|
||||
$this->phpci->logFailure(PHPCI\Helper\Lang::get('could_not_find', 'phpunit'));
|
||||
return false;
|
||||
}
|
||||
|
||||
$cmd = $phpunit . ' --tap %s "%s"';
|
||||
$success = $this->phpci->executeCommand($cmd, $this->args, $this->phpci->buildPath . $directory);
|
||||
chdir($curdir);
|
||||
|
|
|
@ -42,11 +42,6 @@ class TechnicalDebt implements PHPCI\Plugin, PHPCI\ZeroConfigPlugin
|
|||
*/
|
||||
protected $allowed_errors;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $allowed_warnings;
|
||||
|
||||
/**
|
||||
* @var string, based on the assumption the root may not hold the code to be
|
||||
* tested, extends the base path
|
||||
|
@ -94,7 +89,6 @@ class TechnicalDebt implements PHPCI\Plugin, PHPCI\ZeroConfigPlugin
|
|||
$this->directory = $phpci->buildPath;
|
||||
$this->path = '';
|
||||
$this->ignore = $this->phpci->ignore;
|
||||
$this->allowed_warnings = 0;
|
||||
$this->allowed_errors = 0;
|
||||
$this->searches = array('TODO', 'FIXME', 'TO DO', 'FIX ME');
|
||||
|
||||
|
@ -103,9 +97,10 @@ class TechnicalDebt implements PHPCI\Plugin, PHPCI\ZeroConfigPlugin
|
|||
}
|
||||
|
||||
if (isset($options['zero_config']) && $options['zero_config']) {
|
||||
$this->allowed_warnings = -1;
|
||||
$this->allowed_errors = -1;
|
||||
}
|
||||
|
||||
$this->setOptions($options);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -114,7 +109,7 @@ class TechnicalDebt implements PHPCI\Plugin, PHPCI\ZeroConfigPlugin
|
|||
*/
|
||||
protected function setOptions($options)
|
||||
{
|
||||
foreach (array('directory', 'path', 'ignore', 'allowed_warnings', 'allowed_errors') as $key) {
|
||||
foreach (array('directory', 'path', 'ignore', 'allowed_errors') as $key) {
|
||||
if (array_key_exists($key, $options)) {
|
||||
$this->{$key} = $options[$key];
|
||||
}
|
||||
|
|
|
@ -2,8 +2,12 @@
|
|||
|
||||
namespace PHPCI\Plugin\Util;
|
||||
|
||||
use b8\Store\Factory as StoreFactory;
|
||||
use Exception;
|
||||
use PHPCI\Helper\Lang;
|
||||
use \PHPCI\Logging\BuildLogger;
|
||||
use PHPCI\Logging\BuildLogger;
|
||||
use PHPCI\Model\Build;
|
||||
use PHPCI\Store\BuildStore;
|
||||
|
||||
/**
|
||||
* Plugin Executor - Runs the configured plugins for a given build stage.
|
||||
|
@ -21,14 +25,20 @@ class Executor
|
|||
*/
|
||||
protected $pluginFactory;
|
||||
|
||||
/**
|
||||
* @var BuildStore
|
||||
*/
|
||||
protected $store;
|
||||
|
||||
/**
|
||||
* @param Factory $pluginFactory
|
||||
* @param BuildLogger $logger
|
||||
*/
|
||||
public function __construct(Factory $pluginFactory, BuildLogger $logger)
|
||||
public function __construct(Factory $pluginFactory, BuildLogger $logger, BuildStore $store = null)
|
||||
{
|
||||
$this->pluginFactory = $pluginFactory;
|
||||
$this->logger = $logger;
|
||||
$this->store = $store ?: StoreFactory::getStore('Build');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -48,22 +58,29 @@ class Executor
|
|||
foreach ($config[$stage] as $plugin => $options) {
|
||||
$this->logger->log(Lang::get('running_plugin', $plugin));
|
||||
|
||||
// Try and execute it:
|
||||
if ($this->executePlugin($plugin, $options)) {
|
||||
// Execution was successful:
|
||||
$this->logger->logSuccess(Lang::get('plugin_success'));
|
||||
} elseif ($stage == 'setup') {
|
||||
// If we're in the "setup" stage, execution should not continue after
|
||||
// a plugin has failed:
|
||||
throw new \Exception('Plugin failed: ' . $plugin);
|
||||
} else {
|
||||
// If we're in the "test" stage and the plugin is not allowed to fail,
|
||||
// then mark the build as failed:
|
||||
if ($stage == 'test' && (!isset($options['allow_failures']) || !$options['allow_failures'])) {
|
||||
$success = false;
|
||||
}
|
||||
$this->setPluginStatus($stage, $plugin, Build::STATUS_RUNNING);
|
||||
|
||||
// Try and execute it
|
||||
if ($this->executePlugin($plugin, $options)) {
|
||||
// Execution was successful
|
||||
$this->logger->logSuccess(Lang::get('plugin_success'));
|
||||
$this->setPluginStatus($stage, $plugin, Build::STATUS_SUCCESS);
|
||||
} else {
|
||||
// Execution failed
|
||||
$this->logger->logFailure(Lang::get('plugin_failed'));
|
||||
$this->setPluginStatus($stage, $plugin, Build::STATUS_FAILED);
|
||||
|
||||
if ($stage === 'setup') {
|
||||
// If we're in the "setup" stage, execution should not continue after
|
||||
// a plugin has failed:
|
||||
throw new Exception('Plugin failed: ' . $plugin);
|
||||
} elseif ($stage === 'test') {
|
||||
// If we're in the "test" stage and the plugin is not allowed to fail,
|
||||
// then mark the build as failed:
|
||||
if (empty($options['allow_failures'])) {
|
||||
$success = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -91,20 +108,62 @@ class Executor
|
|||
return false;
|
||||
}
|
||||
|
||||
$rtn = true;
|
||||
|
||||
// Try running it:
|
||||
try {
|
||||
// Build and run it
|
||||
$obj = $this->pluginFactory->buildPlugin($class, $options);
|
||||
|
||||
if (!$obj->execute()) {
|
||||
$rtn = false;
|
||||
}
|
||||
return $obj->execute();
|
||||
} catch (\Exception $ex) {
|
||||
$this->logger->logFailure(Lang::get('exception') . $ex->getMessage(), $ex);
|
||||
$rtn = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the status of a plugin for a given stage.
|
||||
*
|
||||
* @param string $stage The builder stage.
|
||||
* @param string $plugin The plugin name.
|
||||
* @param int $status The new status.
|
||||
*/
|
||||
protected function setPluginStatus($stage, $plugin, $status)
|
||||
{
|
||||
$summary = $this->getBuildSummary();
|
||||
|
||||
if (!isset($summary[$stage][$plugin])) {
|
||||
$summary[$stage][$plugin] = array();
|
||||
}
|
||||
|
||||
return $rtn;
|
||||
$summary[$stage][$plugin]['status'] = $status;
|
||||
|
||||
if ($status === Build::STATUS_RUNNING) {
|
||||
$summary[$stage][$plugin]['started'] = time();
|
||||
} elseif ($status >= Build::STATUS_SUCCESS) {
|
||||
$summary[$stage][$plugin]['ended'] = time();
|
||||
}
|
||||
|
||||
$this->setBuildSummary($summary);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the summary data of the current build.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getBuildSummary()
|
||||
{
|
||||
$build = $this->pluginFactory->getResourceFor('PHPCI\Model\Build');
|
||||
$metas = $this->store->getMeta('plugin-summary', $build->getProjectId(), $build->getId());
|
||||
return isset($metas[0]['meta_value']) ? $metas[0]['meta_value'] : array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the summary data of the current build.
|
||||
*
|
||||
* @param array summary
|
||||
*/
|
||||
private function setBuildSummary($summary)
|
||||
{
|
||||
$build = $this->pluginFactory->getResourceFor('PHPCI\Model\Build');
|
||||
$this->store->setMeta($build->getProjectId(), $build->getId(), 'plugin-summary', json_encode($summary));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -150,11 +150,11 @@ class Factory
|
|||
}
|
||||
|
||||
/**
|
||||
* @param null $type
|
||||
* @param null $name
|
||||
* @return null
|
||||
* @param string $type
|
||||
* @param string $name
|
||||
* @return mixed
|
||||
*/
|
||||
private function getResourceFor($type = null, $name = null)
|
||||
public function getResourceFor($type = null, $name = null)
|
||||
{
|
||||
$fullId = $this->getInternalID($type, $name);
|
||||
if (isset($this->container[$fullId])) {
|
||||
|
@ -185,7 +185,7 @@ class Factory
|
|||
return $class->getName();
|
||||
} elseif ($param->isArray()) {
|
||||
return self::TYPE_ARRAY;
|
||||
} elseif ($param->isCallable()) {
|
||||
} elseif (is_callable($param)) {
|
||||
return self::TYPE_CALLABLE;
|
||||
} else {
|
||||
return null;
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
|
||||
namespace PHPCI\Plugin\Util;
|
||||
|
||||
use Exception;
|
||||
use PHPCI\Helper\Lang;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
|
||||
/**
|
||||
* Processes TAP format strings into usable test result data.
|
||||
|
@ -10,18 +12,41 @@ use PHPCI\Helper\Lang;
|
|||
*/
|
||||
class TapParser
|
||||
{
|
||||
const TEST_COUNTS_PATTERN = '/([0-9]+)\.\.([0-9]+)/';
|
||||
const TEST_LINE_PATTERN = '/(ok|not ok)\s+[0-9]+\s+\-\s+([^\n]+)::([^\n]+)/';
|
||||
const TEST_MESSAGE_PATTERN = '/message\:\s+\'([^\']+)\'/';
|
||||
const TEST_COVERAGE_PATTERN = '/Generating code coverage report/';
|
||||
const TEST_SKIP_PATTERN = '/ok\s+[0-9]+\s+\-\s+#\s+SKIP/';
|
||||
const TEST_COUNTS_PATTERN = '/^\d+\.\.(\d+)/';
|
||||
const TEST_LINE_PATTERN = '/^(ok|not ok)(?:\s+\d+)?(?:\s+\-)?\s*(.*?)(?:\s*#\s*(skip|todo)\s*(.*))?\s*$/i';
|
||||
const TEST_YAML_START = '/^(\s*)---/';
|
||||
const TEST_DIAGNOSTIC = '/^#/';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $tapString;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $failures = 0;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $lines;
|
||||
|
||||
/**
|
||||
* @var integer
|
||||
*/
|
||||
protected $lineNumber;
|
||||
|
||||
/**
|
||||
* @var integer
|
||||
*/
|
||||
protected $testCount;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $results;
|
||||
|
||||
/**
|
||||
* Create a new TAP parser for a given string.
|
||||
* @param string $tapString The TAP format string to be parsed.
|
||||
|
@ -38,81 +63,175 @@ class TapParser
|
|||
{
|
||||
// Split up the TAP string into an array of lines, then
|
||||
// trim all of the lines so there's no leading or trailing whitespace.
|
||||
$lines = explode("\n", $this->tapString);
|
||||
$lines = array_map(function ($line) {
|
||||
return trim($line);
|
||||
}, $lines);
|
||||
$this->lines = array_map('rtrim', explode("\n", $this->tapString));
|
||||
$this->lineNumber = 0;
|
||||
|
||||
// Check TAP version:
|
||||
$versionLine = array_shift($lines);
|
||||
$this->testCount = false;
|
||||
$this->results = array();
|
||||
|
||||
if ($versionLine != 'TAP version 13') {
|
||||
throw new \Exception(Lang::get('tap_version'));
|
||||
$header = $this->findTapLog();
|
||||
|
||||
$line = $this->nextLine();
|
||||
if ($line === $header) {
|
||||
throw new Exception("Duplicated TAP log, please check the configration.");
|
||||
}
|
||||
|
||||
if (isset($lines[count($lines) - 1]) && preg_match(self::TEST_COVERAGE_PATTERN, $lines[count($lines) - 1])) {
|
||||
array_pop($lines);
|
||||
if ($lines[count($lines) - 1] == "") {
|
||||
array_pop($lines);
|
||||
while ($line !== false && ($this->testCount === false || count($this->results) < $this->testCount)) {
|
||||
$this->parseLine($line);
|
||||
$line = $this->nextLine();
|
||||
}
|
||||
|
||||
if (count($this->results) !== $this->testCount) {
|
||||
throw new Exception(Lang::get('tap_error'));
|
||||
}
|
||||
|
||||
return $this->results;
|
||||
}
|
||||
|
||||
/** Looks for the start of the TAP log in the string.
|
||||
*
|
||||
* @return string The TAP header line.
|
||||
*
|
||||
* @throws Exception if no TAP log is found or versions mismatch.
|
||||
*/
|
||||
protected function findTapLog()
|
||||
{
|
||||
// Look for the beggning of the TAP output
|
||||
do {
|
||||
$header = $this->nextLine();
|
||||
} while ($header !== false && substr($header, 0, 12) !== 'TAP version ');
|
||||
|
||||
//
|
||||
if ($header === false) {
|
||||
throw new Exception('No TAP log found, please check the configuration.');
|
||||
} elseif ($header !== 'TAP version 13') {
|
||||
throw new Exception(Lang::get('tap_version'));
|
||||
}
|
||||
|
||||
return $header;
|
||||
}
|
||||
|
||||
/** Fetch the next line.
|
||||
*
|
||||
* @return string|false The next line or false if the end has been reached.
|
||||
*/
|
||||
protected function nextLine()
|
||||
{
|
||||
if ($this->lineNumber < count($this->lines)) {
|
||||
return $this->lines[$this->lineNumber++];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Parse a single line.
|
||||
*
|
||||
* @param string $line
|
||||
*/
|
||||
protected function parseLine($line)
|
||||
{
|
||||
if (preg_match(self::TEST_COUNTS_PATTERN, $line, $matches)) {
|
||||
$this->testCount = intval($matches[1]);
|
||||
|
||||
} elseif (preg_match(self::TEST_DIAGNOSTIC, $line)) {
|
||||
return;
|
||||
|
||||
} elseif (preg_match(self::TEST_LINE_PATTERN, $line, $matches)) {
|
||||
$this->results[] = $this->processTestLine(
|
||||
$matches[1],
|
||||
isset($matches[2]) ? $matches[2] : '',
|
||||
isset($matches[3]) ? $matches[3] : null,
|
||||
isset($matches[4]) ? $matches[4] : null
|
||||
);
|
||||
|
||||
} elseif (preg_match(self::TEST_YAML_START, $line, $matches)) {
|
||||
$diagnostic = $this->processYamlBlock($matches[1]);
|
||||
$test = array_pop($this->results);
|
||||
if (isset($test['message'], $diagnostic['message'])) {
|
||||
$test['message'] .= PHP_EOL . $diagnostic['message'];
|
||||
unset($diagnostic['message']);
|
||||
}
|
||||
$this->results[] = array_replace($test, $diagnostic);
|
||||
|
||||
} else {
|
||||
throw new Exception(sprintf('Incorrect TAP data, line %d: %s', $this->lineNumber, $line));
|
||||
}
|
||||
|
||||
$matches = array();
|
||||
$totalTests = 0;
|
||||
if (preg_match(self::TEST_COUNTS_PATTERN, $lines[0], $matches)) {
|
||||
array_shift($lines);
|
||||
$totalTests = (int) $matches[2];
|
||||
}
|
||||
|
||||
if (isset($lines[count($lines) - 1]) &&
|
||||
preg_match(self::TEST_COUNTS_PATTERN, $lines[count($lines) - 1], $matches)) {
|
||||
array_pop($lines);
|
||||
$totalTests = (int) $matches[2];
|
||||
}
|
||||
|
||||
$rtn = $this->processTestLines($lines);
|
||||
|
||||
if ($totalTests != count($rtn)) {
|
||||
throw new \Exception(Lang::get('tap_error'));
|
||||
}
|
||||
|
||||
return $rtn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the individual test lines within a TAP string.
|
||||
* @param $lines
|
||||
* Process an individual test line.
|
||||
*
|
||||
* @param string $result
|
||||
* @param string $message
|
||||
* @param string $directive
|
||||
* @param string $reason
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function processTestLines($lines)
|
||||
protected function processTestLine($result, $message, $directive, $reason)
|
||||
{
|
||||
$rtn = array();
|
||||
$test = array(
|
||||
'pass' => true,
|
||||
'message' => $message,
|
||||
'severity' => 'success',
|
||||
);
|
||||
|
||||
foreach ($lines as $line) {
|
||||
$matches = array();
|
||||
|
||||
if (preg_match(self::TEST_LINE_PATTERN, $line, $matches)) {
|
||||
$ok = ($matches[1] == 'ok' ? true : false);
|
||||
|
||||
if (!$ok) {
|
||||
$this->failures++;
|
||||
}
|
||||
|
||||
$item = array(
|
||||
'pass' => $ok,
|
||||
'suite' => $matches[2],
|
||||
'test' => $matches[3],
|
||||
);
|
||||
|
||||
$rtn[] = $item;
|
||||
} elseif (preg_match(self::TEST_SKIP_PATTERN, $line, $matches)) {
|
||||
$rtn[] = array('message' => 'SKIP');
|
||||
} elseif (preg_match(self::TEST_MESSAGE_PATTERN, $line, $matches)) {
|
||||
$rtn[count($rtn) - 1]['message'] = $matches[1];
|
||||
}
|
||||
if ($result !== 'ok') {
|
||||
$test['pass'] = false;
|
||||
$test['severity'] = substr($message, 0, 6) === 'Error:' ? 'error' : 'fail';
|
||||
$this->failures++;
|
||||
}
|
||||
|
||||
return $rtn;
|
||||
if ($directive) {
|
||||
$test = $this->processDirective($test, $directive, $reason);
|
||||
}
|
||||
|
||||
return $test;
|
||||
}
|
||||
|
||||
/** Process an indented Yaml block.
|
||||
*
|
||||
* @param string $indent The block indentation to ignore.
|
||||
*
|
||||
* @return array The processed Yaml content.
|
||||
*/
|
||||
protected function processYamlBlock($indent)
|
||||
{
|
||||
$startLine = $this->lineNumber+1;
|
||||
$endLine = $indent.'...';
|
||||
$yamlLines = array();
|
||||
do {
|
||||
$line = $this->nextLine();
|
||||
if ($line === false) {
|
||||
throw new Exception(Lang::get('tap_error_endless_yaml', $startLine));
|
||||
} elseif ($line === $endLine) {
|
||||
break;
|
||||
}
|
||||
$yamlLines[] = substr($line, strlen($indent));
|
||||
|
||||
} while (true);
|
||||
|
||||
return Yaml::parse(join("\n", $yamlLines));
|
||||
}
|
||||
|
||||
/** Process a TAP directive
|
||||
*
|
||||
* @param array $test
|
||||
* @param string $directive
|
||||
* @param string $reason
|
||||
* @return array
|
||||
*/
|
||||
protected function processDirective($test, $directive, $reason)
|
||||
{
|
||||
$test['severity'] = strtolower($directive) === 'skip' ? 'skipped' : 'todo';
|
||||
|
||||
if (!empty($reason)) {
|
||||
if (!empty($test['message'])) {
|
||||
$test['message'] .= ', '.$test['severity'].': ';
|
||||
}
|
||||
$test['message'] .= $reason;
|
||||
}
|
||||
|
||||
return $test;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
113
PHPCI/Plugin/Util/TestResultParsers/Codeception.php
Normal file
113
PHPCI/Plugin/Util/TestResultParsers/Codeception.php
Normal file
|
@ -0,0 +1,113 @@
|
|||
<?php
|
||||
|
||||
namespace PHPCI\Plugin\Util\TestResultParsers;
|
||||
|
||||
use PHPCI\Builder;
|
||||
|
||||
/**
|
||||
* Class Codeception
|
||||
*
|
||||
* @author Adam Cooper <adam@networkpie.co.uk>
|
||||
* @package PHPCI\Plugin\Util\TestResultParsers
|
||||
*/
|
||||
class Codeception implements ParserInterface
|
||||
{
|
||||
protected $phpci;
|
||||
protected $resultsXml;
|
||||
|
||||
protected $results;
|
||||
|
||||
protected $totalTests;
|
||||
protected $totalTimeTaken;
|
||||
protected $totalFailures;
|
||||
|
||||
/**
|
||||
* @param Builder $phpci
|
||||
* @param $resultsXml
|
||||
*/
|
||||
public function __construct(Builder $phpci, $resultsXml)
|
||||
{
|
||||
$this->phpci = $phpci;
|
||||
$this->resultsXml = $resultsXml;
|
||||
|
||||
$this->totalTests = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array An array of key/value pairs for storage in the plugins result metadata
|
||||
*/
|
||||
public function parse()
|
||||
{
|
||||
$rtn = array();
|
||||
|
||||
$this->results = new \SimpleXMLElement($this->resultsXml);
|
||||
|
||||
// calculate total results
|
||||
foreach ($this->results->testsuite as $testsuite) {
|
||||
$this->totalTests += (int) $testsuite['tests'];
|
||||
$this->totalTimeTaken += (float) $testsuite['time'];
|
||||
$this->totalFailures += (int) $testsuite['failures'];
|
||||
|
||||
foreach ($testsuite->testcase as $testcase) {
|
||||
$testresult = array(
|
||||
'suite' => (string) $testsuite['name'],
|
||||
'file' => str_replace($this->phpci->buildPath, '/', (string) $testcase['file']),
|
||||
'name' => (string) $testcase['name'],
|
||||
'feature' => (string) $testcase['feature'],
|
||||
'assertions' => (int) $testcase['assertions'],
|
||||
'time' => (float) $testcase['time']
|
||||
);
|
||||
|
||||
if (isset($testcase['class'])) {
|
||||
$testresult['class'] = (string) $testcase['class'];
|
||||
}
|
||||
|
||||
// PHPUnit testcases does not have feature field. Use class::method instead
|
||||
if (!$testresult['feature']) {
|
||||
$testresult['feature'] = sprintf('%s::%s', $testresult['class'], $testresult['name']);
|
||||
}
|
||||
|
||||
if (isset($testcase->failure)) {
|
||||
$testresult['pass'] = false;
|
||||
$testresult['message'] = (string) $testcase->failure;
|
||||
} else {
|
||||
$testresult['pass'] = true;
|
||||
}
|
||||
|
||||
$rtn[] = $testresult;
|
||||
}
|
||||
}
|
||||
|
||||
return $rtn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the total number of tests performed.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getTotalTests()
|
||||
{
|
||||
return $this->totalTests;
|
||||
}
|
||||
|
||||
/**
|
||||
* The time take to complete all tests
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getTotalTimeTaken()
|
||||
{
|
||||
return $this->totalTimeTaken;
|
||||
}
|
||||
|
||||
/**
|
||||
* A count of the test failures
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getTotalFailures()
|
||||
{
|
||||
return $this->totalFailures;
|
||||
}
|
||||
}
|
16
PHPCI/Plugin/Util/TestResultParsers/ParserInterface.php
Normal file
16
PHPCI/Plugin/Util/TestResultParsers/ParserInterface.php
Normal file
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace PHPCI\Plugin\Util\TestResultParsers;
|
||||
|
||||
interface ParserInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return array An array of key/value pairs for storage in the plugins result metadata
|
||||
*/
|
||||
public function parse();
|
||||
|
||||
public function getTotalTests();
|
||||
public function getTotalTimeTaken();
|
||||
public function getTotalFailures();
|
||||
}
|
|
@ -61,8 +61,8 @@ class Wipe implements \PHPCI\Plugin
|
|||
if (IS_WIN) {
|
||||
$cmd = 'rmdir /S /Q "%s"';
|
||||
}
|
||||
$success = $this->phpci->executeCommand($cmd, $this->directory);
|
||||
return $this->phpci->executeCommand($cmd, $this->directory);
|
||||
}
|
||||
return $success;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -132,8 +132,8 @@ class XMPP implements \PHPCI\Plugin
|
|||
*/
|
||||
public function findConfigFile()
|
||||
{
|
||||
if (file_exists('.sendxmpprc')) {
|
||||
if (md5(file_get_contents('.sendxmpprc')) !== md5($this->getConfigFormat())) {
|
||||
if (file_exists($this->phpci->buildPath . '/.sendxmpprc')) {
|
||||
if (md5(file_get_contents($this->phpci->buildPath . '/.sendxmpprc')) !== md5($this->getConfigFormat())) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -148,12 +148,7 @@ class XMPP implements \PHPCI\Plugin
|
|||
*/
|
||||
public function execute()
|
||||
{
|
||||
$sendxmpp = $this->phpci->findBinary('/usr/bin/sendxmpp');
|
||||
|
||||
if (!$sendxmpp) {
|
||||
$this->phpci->logFailure('Could not find sendxmpp.');
|
||||
return false;
|
||||
}
|
||||
$sendxmpp = $this->phpci->findBinary('sendxmpp');
|
||||
|
||||
/*
|
||||
* Without recipients we can't send notification
|
||||
|
@ -165,9 +160,10 @@ class XMPP implements \PHPCI\Plugin
|
|||
/*
|
||||
* Try to build conf file
|
||||
*/
|
||||
$config_file = $this->phpci->buildPath . '/.sendxmpprc';
|
||||
if (is_null($this->findConfigFile())) {
|
||||
file_put_contents('.sendxmpprc', $this->getConfigFormat());
|
||||
chmod('.sendxmpprc', 0600);
|
||||
file_put_contents($config_file, $this->getConfigFormat());
|
||||
chmod($config_file, 0600);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -178,7 +174,7 @@ class XMPP implements \PHPCI\Plugin
|
|||
$tls = ' -t';
|
||||
}
|
||||
|
||||
$message_file = uniqid('xmppmessage');
|
||||
$message_file = $this->phpci->buildPath . '/' . uniqid('xmppmessage');
|
||||
if ($this->buildMessage($message_file) === false) {
|
||||
return false;
|
||||
}
|
||||
|
@ -186,10 +182,10 @@ class XMPP implements \PHPCI\Plugin
|
|||
/*
|
||||
* Send XMPP notification for all recipients
|
||||
*/
|
||||
$cmd = $sendxmpp . "%s -f .sendxmpprc -m %s %s";
|
||||
$cmd = $sendxmpp . "%s -f %s -m %s %s";
|
||||
$recipients = implode(' ', $this->recipients);
|
||||
|
||||
$success = $this->phpci->executeCommand($cmd, $tls, $message_file, $recipients);
|
||||
$success = $this->phpci->executeCommand($cmd, $tls, $config_file, $message_file, $recipients);
|
||||
|
||||
print $this->phpci->getLastOutput();
|
||||
|
||||
|
|
63
PHPCI/ProcessControl/Factory.php
Normal file
63
PHPCI/ProcessControl/Factory.php
Normal file
|
@ -0,0 +1,63 @@
|
|||
<?php
|
||||
/**
|
||||
* PHPCI - Continuous Integration for PHP
|
||||
*
|
||||
* @copyright Copyright 2015, Block 8 Limited.
|
||||
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
|
||||
* @link https://www.phptesting.org/
|
||||
*/
|
||||
|
||||
namespace PHPCI\ProcessControl;
|
||||
|
||||
/**
|
||||
* Construct an appropriate ProcessControl instance.
|
||||
*
|
||||
* @author Adirelle <adirelle@gmail.com>
|
||||
*/
|
||||
class Factory
|
||||
{
|
||||
/**
|
||||
* ProcessControl singleton.
|
||||
*
|
||||
* @var ProcessControlInterface
|
||||
*/
|
||||
protected static $instance = null;
|
||||
|
||||
/**
|
||||
* Returns the ProcessControl singleton.
|
||||
*
|
||||
* @return ProcessControlInterface
|
||||
*/
|
||||
public static function getInstance()
|
||||
{
|
||||
if (static::$instance === null) {
|
||||
static::$instance = static::createProcessControl();
|
||||
}
|
||||
return static::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a ProcessControl depending on available extensions and the underlying OS.
|
||||
*
|
||||
* Check PosixProcessControl, WindowsProcessControl and UnixProcessControl, in that order.
|
||||
*
|
||||
* @return ProcessControlInterface
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public static function createProcessControl()
|
||||
{
|
||||
switch(true) {
|
||||
case PosixProcessControl::isAvailable():
|
||||
return new PosixProcessControl();
|
||||
|
||||
case WindowsProcessControl::isAvailable():
|
||||
return new WindowsProcessControl();
|
||||
|
||||
case UnixProcessControl::isAvailable():
|
||||
return new UnixProcessControl();
|
||||
}
|
||||
|
||||
throw new \Exception("No ProcessControl implementation available.");
|
||||
}
|
||||
}
|
52
PHPCI/ProcessControl/PosixProcessControl.php
Normal file
52
PHPCI/ProcessControl/PosixProcessControl.php
Normal file
|
@ -0,0 +1,52 @@
|
|||
<?php
|
||||
/**
|
||||
* PHPCI - Continuous Integration for PHP
|
||||
*
|
||||
* @copyright Copyright 2015, Block 8 Limited.
|
||||
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
|
||||
* @link https://www.phptesting.org/
|
||||
*/
|
||||
|
||||
namespace PHPCI\ProcessControl;
|
||||
|
||||
/**
|
||||
* Control process using the POSIX extension.
|
||||
*
|
||||
* @author Adirelle <adirelle@gmail.com>
|
||||
*/
|
||||
class PosixProcessControl implements ProcessControlInterface
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @param int $pid
|
||||
* @return bool
|
||||
*/
|
||||
public function isRunning($pid)
|
||||
{
|
||||
// Signal "0" is not sent to the process, but posix_kill checks the process anyway;
|
||||
return posix_kill($pid, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a TERMINATE or KILL signal to the process using posix_kill.
|
||||
*
|
||||
* @param int $pid
|
||||
* @param bool $forcefully Whetehr to send TERMINATE (false) or KILL (true).
|
||||
*/
|
||||
public function kill($pid, $forcefully = false)
|
||||
{
|
||||
posix_kill($pid, $forcefully ? 9 : 15);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether this posix_kill is available.
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public static function isAvailable()
|
||||
{
|
||||
return function_exists('posix_kill');
|
||||
}
|
||||
}
|
33
PHPCI/ProcessControl/ProcessControlInterface.php
Normal file
33
PHPCI/ProcessControl/ProcessControlInterface.php
Normal file
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
/**
|
||||
* PHPCI - Continuous Integration for PHP
|
||||
*
|
||||
* @copyright Copyright 2015, Block 8 Limited.
|
||||
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
|
||||
* @link https://www.phptesting.org/
|
||||
*/
|
||||
|
||||
namespace PHPCI\ProcessControl;
|
||||
|
||||
/**
|
||||
* A stateless service to check and kill system processes.
|
||||
*
|
||||
* @author Adirelle <adirelle@gmail.com>
|
||||
*/
|
||||
interface ProcessControlInterface
|
||||
{
|
||||
/** Checks if a process exists.
|
||||
*
|
||||
* @param int $pid The process identifier.
|
||||
*
|
||||
* @return boolean true is the process is running, else false.
|
||||
*/
|
||||
public function isRunning($pid);
|
||||
|
||||
/** Terminate a running process.
|
||||
*
|
||||
* @param int $pid The process identifier.
|
||||
* @param bool $forcefully Whether to gently (false) or forcefully (true) terminate the process.
|
||||
*/
|
||||
public function kill($pid, $forcefully = false);
|
||||
}
|
54
PHPCI/ProcessControl/UnixProcessControl.php
Normal file
54
PHPCI/ProcessControl/UnixProcessControl.php
Normal file
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
/**
|
||||
* PHPCI - Continuous Integration for PHP
|
||||
*
|
||||
* @copyright Copyright 2015, Block 8 Limited.
|
||||
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
|
||||
* @link https://www.phptesting.org/
|
||||
*/
|
||||
|
||||
namespace PHPCI\ProcessControl;
|
||||
|
||||
/**
|
||||
* Control processes using the "ps" and "kill" commands.
|
||||
*
|
||||
* @author Adirelle <adirelle@gmail.com>
|
||||
*/
|
||||
class UnixProcessControl implements ProcessControlInterface
|
||||
{
|
||||
/**
|
||||
* Check process using the "ps" command.
|
||||
*
|
||||
* @param int $pid
|
||||
* @return boolean
|
||||
*/
|
||||
public function isRunning($pid)
|
||||
{
|
||||
$output = $exitCode = null;
|
||||
exec(sprintf("ps %d", $pid), $output, $exitCode);
|
||||
return $exitCode === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a signal using the "kill" command.
|
||||
*
|
||||
* @param int $pid
|
||||
* @param bool $forcefully
|
||||
*/
|
||||
public function kill($pid, $forcefully = false)
|
||||
{
|
||||
exec(sprintf("kill -%d %d", $forcefully ? 9 : 15, $pid));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the commands "ps" and "kill" are available.
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public static function isAvailable()
|
||||
{
|
||||
return DIRECTORY_SEPARATOR === '/' && exec("which ps") && exec("which kill");
|
||||
}
|
||||
}
|
54
PHPCI/ProcessControl/WindowsProcessControl.php
Normal file
54
PHPCI/ProcessControl/WindowsProcessControl.php
Normal file
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
/**
|
||||
* PHPCI - Continuous Integration for PHP
|
||||
*
|
||||
* @copyright Copyright 2015, Block 8 Limited.
|
||||
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
|
||||
* @link https://www.phptesting.org/
|
||||
*/
|
||||
|
||||
namespace PHPCI\ProcessControl;
|
||||
|
||||
/**
|
||||
* Control processes using the "tasklist" and "taskkill" commands.
|
||||
*
|
||||
* @author Adirelle <adirelle@gmail.com>
|
||||
*/
|
||||
class WindowsProcessControl implements ProcessControlInterface
|
||||
{
|
||||
/**
|
||||
* Check if the process is running using the "tasklist" command.
|
||||
*
|
||||
* @param type $pid
|
||||
* @return bool
|
||||
*/
|
||||
public function isRunning($pid)
|
||||
{
|
||||
$lastLine = exec(sprintf('tasklist /fi "PID eq %d" /nh /fo csv 2>nul:', $pid));
|
||||
$record = str_getcsv($lastLine);
|
||||
return isset($record[1]) && intval($record[1]) === $pid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Terminate the process using the "taskkill" command.
|
||||
*
|
||||
* @param type $pid
|
||||
* @param bool $forcefully
|
||||
*/
|
||||
public function kill($pid, $forcefully = false)
|
||||
{
|
||||
exec(sprintf("taskkill /t /pid %d %s 2>nul:", $pid, $forcefully ? '/f' : ''));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the commands "tasklist" and "taskkill" are available.
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public static function isAvailable()
|
||||
{
|
||||
return DIRECTORY_SEPARATOR === '\\' && exec("where tasklist") && exec("where taskkill");
|
||||
}
|
||||
}
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
namespace PHPCI\Service;
|
||||
|
||||
use PHPCI\Helper\Lang;
|
||||
use PHPCI\Model\Build;
|
||||
use PHPCI\Model\Project;
|
||||
use PHPCI\Store\BuildStore;
|
||||
|
@ -59,6 +60,7 @@ class BuildService
|
|||
$build->setCommitId($commitId);
|
||||
} else {
|
||||
$build->setCommitId('Manual');
|
||||
$build->setCommitMessage(Lang::get('manual_build'));
|
||||
}
|
||||
|
||||
if (!is_null($branch)) {
|
||||
|
@ -112,6 +114,7 @@ class BuildService
|
|||
*/
|
||||
public function deleteBuild(Build $build)
|
||||
{
|
||||
$build->removeBuildDirectory();
|
||||
return $this->buildStore->delete($build);
|
||||
}
|
||||
}
|
||||
|
|
222
PHPCI/Service/BuildStatusService.php
Normal file
222
PHPCI/Service/BuildStatusService.php
Normal file
|
@ -0,0 +1,222 @@
|
|||
<?php
|
||||
/**
|
||||
* 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/
|
||||
*/
|
||||
|
||||
namespace PHPCI\Service;
|
||||
|
||||
use PHPCI\Model\Project;
|
||||
use PHPCI\Model\Build;
|
||||
|
||||
/**
|
||||
* Class BuildStatusService
|
||||
* @package PHPCI\Service
|
||||
*/
|
||||
class BuildStatusService
|
||||
{
|
||||
/* @var BuildStatusService */
|
||||
protected $prevService = null;
|
||||
|
||||
/* @var Project */
|
||||
protected $project;
|
||||
|
||||
/** @var string */
|
||||
protected $branch;
|
||||
|
||||
/* @var Build */
|
||||
protected $build;
|
||||
|
||||
/** @var string */
|
||||
protected $url;
|
||||
|
||||
/** @var array */
|
||||
protected $finishedStatusIds = array(
|
||||
Build::STATUS_SUCCESS,
|
||||
Build::STATUS_FAILED,
|
||||
);
|
||||
|
||||
/**
|
||||
* @param $branch
|
||||
* @param Project $project
|
||||
* @param Build $build
|
||||
* @param bool $isParent
|
||||
*/
|
||||
public function __construct(
|
||||
$branch,
|
||||
Project $project,
|
||||
Build $build = null,
|
||||
$isParent = false
|
||||
) {
|
||||
$this->project = $project;
|
||||
$this->branch = $branch;
|
||||
$this->build = $build;
|
||||
if ($this->build) {
|
||||
$this->loadParentBuild($isParent);
|
||||
}
|
||||
if (defined('PHPCI_URL')) {
|
||||
$this->setUrl(PHPCI_URL);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $url
|
||||
*/
|
||||
public function setUrl($url)
|
||||
{
|
||||
$this->url = $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Build
|
||||
*/
|
||||
public function getBuild()
|
||||
{
|
||||
return $this->build;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $isParent
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function loadParentBuild($isParent = true)
|
||||
{
|
||||
if ($isParent === false && !$this->isFinished()) {
|
||||
$lastFinishedBuild = $this->project->getLatestBuild($this->branch, $this->finishedStatusIds);
|
||||
|
||||
if ($lastFinishedBuild) {
|
||||
$this->prevService = new BuildStatusService(
|
||||
$this->branch,
|
||||
$this->project,
|
||||
$lastFinishedBuild,
|
||||
true
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getActivity()
|
||||
{
|
||||
if (in_array($this->build->getStatus(), $this->finishedStatusIds)) {
|
||||
return 'Sleeping';
|
||||
} elseif ($this->build->getStatus() == Build::STATUS_NEW) {
|
||||
return 'Pending';
|
||||
} elseif ($this->build->getStatus() == Build::STATUS_RUNNING) {
|
||||
return 'Building';
|
||||
}
|
||||
return 'Unknown';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->project->getTitle() . ' / ' . $this->branch;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isFinished()
|
||||
{
|
||||
if (in_array($this->build->getStatus(), $this->finishedStatusIds)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null|Build
|
||||
*/
|
||||
public function getFinishedBuildInfo()
|
||||
{
|
||||
if ($this->isFinished()) {
|
||||
return $this->build;
|
||||
} elseif ($this->prevService) {
|
||||
return $this->prevService->getBuild();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int|string
|
||||
*/
|
||||
public function getLastBuildLabel()
|
||||
{
|
||||
if ($buildInfo = $this->getFinishedBuildInfo()) {
|
||||
return $buildInfo->getId();
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getLastBuildTime()
|
||||
{
|
||||
$dateFormat = 'Y-m-d\\TH:i:sO';
|
||||
if ($buildInfo = $this->getFinishedBuildInfo()) {
|
||||
return ($buildInfo->getFinished()) ? $buildInfo->getFinished()->format($dateFormat) : '';
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Build $build
|
||||
* @return string
|
||||
*/
|
||||
public function getBuildStatus(Build $build)
|
||||
{
|
||||
switch ($build->getStatus()) {
|
||||
case Build::STATUS_SUCCESS:
|
||||
return 'Success';
|
||||
case Build::STATUS_FAILED:
|
||||
return 'Failure';
|
||||
}
|
||||
return 'Unknown';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getLastBuildStatus()
|
||||
{
|
||||
if ($build = $this->getFinishedBuildInfo()) {
|
||||
return $this->getBuildStatus($build);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getBuildUrl()
|
||||
{
|
||||
return $this->url . 'build/view/' . $this->build->getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
if (!$this->build) {
|
||||
return array();
|
||||
}
|
||||
return array(
|
||||
'name' => $this->getName(),
|
||||
'activity' => $this->getActivity(),
|
||||
'lastBuildLabel' => $this->getLastBuildLabel(),
|
||||
'lastBuildStatus' => $this->getLastBuildStatus(),
|
||||
'lastBuildTime' => $this->getLastBuildTime(),
|
||||
'webUrl' => $this->getBuildUrl(),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -59,7 +59,7 @@ class UserStoreBase extends Store
|
|||
|
||||
/**
|
||||
* Returns a User model by Email.
|
||||
* @param mixed $value
|
||||
* @param string $value
|
||||
* @param string $useConnection
|
||||
* @throws HttpException
|
||||
* @return \@appNamespace\Model\User|null
|
||||
|
@ -82,4 +82,30 @@ class UserStoreBase extends Store
|
|||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a User model by Email.
|
||||
* @param string $value
|
||||
* @param string $useConnection
|
||||
* @throws HttpException
|
||||
* @return \@appNamespace\Model\User|null
|
||||
*/
|
||||
public function getByLoginOrEmail($value, $useConnection = 'read')
|
||||
{
|
||||
if (is_null($value)) {
|
||||
throw new HttpException('Value passed to ' . __FUNCTION__ . ' cannot be null.');
|
||||
}
|
||||
|
||||
$query = 'SELECT * FROM `user` WHERE `name` = :value OR `email` = :value LIMIT 1';
|
||||
$stmt = Database::getConnection($useConnection)->prepare($query);
|
||||
$stmt->bindValue(':value', $value);
|
||||
|
||||
if ($stmt->execute()) {
|
||||
if ($data = $stmt->fetch(\PDO::FETCH_ASSOC)) {
|
||||
return new User($data);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -107,6 +107,27 @@ class BuildStore extends BuildStoreBase
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all registered branches for project
|
||||
*
|
||||
* @param $projectId
|
||||
* @return array
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function getBuildBranches($projectId)
|
||||
{
|
||||
$query = 'SELECT DISTINCT `branch` FROM `build` WHERE `project_id` = :project_id';
|
||||
$stmt = Database::getConnection('read')->prepare($query);
|
||||
$stmt->bindValue(':project_id', $projectId);
|
||||
|
||||
if ($stmt->execute()) {
|
||||
$res = $stmt->fetchAll(\PDO::FETCH_COLUMN);
|
||||
return $res;
|
||||
} else {
|
||||
return array();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return build metadata by key, project and optionally build id.
|
||||
* @param $key
|
||||
|
@ -144,7 +165,9 @@ class BuildStore extends BuildStoreBase
|
|||
$stmt->bindValue(':projectId', (int)$projectId, \PDO::PARAM_INT);
|
||||
$stmt->bindValue(':buildId', (int)$buildId, \PDO::PARAM_INT);
|
||||
$stmt->bindValue(':numResults', (int)$numResults, \PDO::PARAM_INT);
|
||||
$stmt->bindValue(':branch', $branch, \PDO::PARAM_STR);
|
||||
if (!is_null($branch)) {
|
||||
$stmt->bindValue(':branch', $branch, \PDO::PARAM_STR);
|
||||
}
|
||||
|
||||
if ($stmt->execute()) {
|
||||
$rtn = $stmt->fetchAll(\PDO::FETCH_ASSOC);
|
||||
|
|
|
@ -39,6 +39,7 @@ switch($build->getStatus())
|
|||
?>
|
||||
<tr class="<?php print $cls; ?>">
|
||||
<td><a href="<?php echo PHPCI_URL ?>build/view/<?php print $build->getId(); ?>">#<?php print str_pad($build->getId(), 6, '0', STR_PAD_LEFT); ?></a></td>
|
||||
<td><?php print $build->getCreated()->format('Y-m-d H:i:s'); ?></td>
|
||||
<td><a href="<?php echo PHPCI_URL ?>project/view/<?php print $build->getProjectId(); ?>">
|
||||
<?php
|
||||
if (is_object($build->getProject())) {
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
<div style="background: #900; padding: 25px;">
|
||||
<div style="background: #fff; padding: 15px; border-radius: 5px">
|
||||
<div style="font-family: arial, verdana, sans-serif; font-size: 25px; margin-bottom: 15px">
|
||||
<?php print $project->getTitle(); ?> - Build #<?php print $build->getId(); ?>
|
||||
</div>
|
||||
|
||||
<div style="font-family: arial, verdana, sans-serif; font-size: 15px">
|
||||
<p>Your commit <strong><?php print $build->getCommitId(); ?></strong> caused a failed build in project <strong><?php print $project->getTitle(); ?></strong>.</p>
|
||||
|
||||
<p style="margin: 10px; background: #fafafa"><?php print $build->getCommitMessage(); ?></p>
|
||||
|
||||
<p>Please review <a href="<?php print $build->getCommitLink(); ?>">your commit</a> and the <a href="<?php print PHPCI_URL . 'build/view/' . $build->getId(); ?>">build log</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
28
PHPCI/View/Email/layout.phtml
Normal file
28
PHPCI/View/Email/layout.phtml
Normal file
|
@ -0,0 +1,28 @@
|
|||
<html>
|
||||
<head>
|
||||
<style>
|
||||
<?php include(__DIR__ . '/../../../public/assets/css/ansi-colors.css'); ?>
|
||||
body { font-family: arial, verdana, sans-serif; font-size: 15px; }
|
||||
header { font-size: 25px; margin-bottom: 15px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div style="background: #<?php print $build->isSuccessful() ? '090' : '900'; ?>; padding: 25px;">
|
||||
<div style="background: #fff; padding: 15px; border-radius: 5px">
|
||||
<header><?php print $project->getTitle(); ?> - Build #<?php print $build->getId(); ?></header>
|
||||
<div>
|
||||
<p>
|
||||
Your commit <strong><?php print $build->getCommitId(); ?></strong> generated a
|
||||
<?php print $build->isSuccessful() ? 'successful' : 'failed'; ?> build in project
|
||||
<strong><?php print $project->getTitle(); ?></strong>.
|
||||
</p>
|
||||
<?php print $content; ?>
|
||||
</div>
|
||||
<footer>
|
||||
You can review <a href="<?php print $build->getCommitLink(); ?>">your commit</a>
|
||||
and the <a href="<?php print PHPCI_URL . 'build/view/' . $build->getId(); ?>">build log</a>.
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
2
PHPCI/View/Email/long.phtml
Normal file
2
PHPCI/View/Email/long.phtml
Normal file
|
@ -0,0 +1,2 @@
|
|||
<p style="margin: 10px; background: #fafafa"><?php print $build->getCommitMessage(); ?></p>
|
||||
<pre class="ansi_color_bg_black ansi_color_fg_white" style="padding: 4px"><?php print \PHPCI\Helper\AnsiConverter::convert($build->getLog()); ?></pre>
|
1
PHPCI/View/Email/short.phtml
Normal file
1
PHPCI/View/Email/short.phtml
Normal file
|
@ -0,0 +1 @@
|
|||
<p style="margin: 10px; background: #fafafa"><?php print $build->getCommitMessage(); ?></p>
|
|
@ -1,15 +0,0 @@
|
|||
<div style="background: #090; padding: 25px;">
|
||||
<div style="background: #fff; padding: 15px; border-radius: 5px">
|
||||
<div style="font-family: arial, verdana, sans-serif; font-size: 25px; margin-bottom: 15px">
|
||||
<?php print $project->getTitle(); ?> - Build #<?php print $build->getId(); ?>
|
||||
</div>
|
||||
|
||||
<div style="font-family: arial, verdana, sans-serif; font-size: 15px">
|
||||
<p>Your commit <strong><?php print $build->getCommitId(); ?></strong> genrate a successfull build in project <strong><?php print $project->getTitle(); ?></strong>.</p>
|
||||
|
||||
<p style="margin: 10px; background: #fafafa"><?php print $build->getCommitMessage(); ?></p>
|
||||
<pre><?php print $build->getLog(); ?></pre>
|
||||
<p>You can review <a href="<?php print $build->getCommitLink(); ?>">your commit</a> and the <a href="<?php print PHPCI_URL . 'build/view/' . $build->getId(); ?>">build log</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
<div class="clearfix" style="margin-bottom: 20px;">
|
||||
<div class="pull-right btn-group">
|
||||
<a class="btn btn-success" href="<?php print PHPCI_URL . 'project/build/' . $project->getId(); ?>">
|
||||
<a class="btn btn-success" href="<?php print PHPCI_URL . 'project/build/' . $project->getId(); ?>/<?php echo urlencode($branch) ?>">
|
||||
<?php Lang::out('build_now'); ?>
|
||||
</a>
|
||||
|
||||
|
@ -36,13 +36,13 @@
|
|||
<div class="col-lg-9 col-md-8 col-sm-8">
|
||||
<div class="box box-primary">
|
||||
<div class="box-header">
|
||||
|
||||
<h3 class="box-title"><?php Lang::out('builds'); ?></h3>
|
||||
<h3 class="box-title"><?php Lang::out('builds'); ?> (<?php print $total; ?>)</h3>
|
||||
</div>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><?php Lang::out('id'); ?></th>
|
||||
<th><?php Lang::out('date'); ?></th>
|
||||
<th><?php Lang::out('project'); ?></th>
|
||||
<th class="hidden-md hidden-sm hidden-xs"><?php Lang::out('commit'); ?></th>
|
||||
<th><?php Lang::out('branch'); ?></th>
|
||||
|
@ -153,4 +153,4 @@ if ($page < $pages - 1) {
|
|||
|
||||
print '</ul></div>';
|
||||
|
||||
?>
|
||||
?>
|
||||
|
|
|
@ -59,20 +59,20 @@
|
|||
$returnTo = PHPCI_URL . 'settings/github-callback';
|
||||
$githubUri = 'https://github.com/login/oauth/authorize?client_id='.$id.'&scope=repo&redirect_uri=' . $returnTo;
|
||||
?>
|
||||
<?php if (!empty($id) && empty($settings['phpci']['github']['token'])): ?>
|
||||
<p class="alert alert-warning clearfix">
|
||||
<?php Lang::out('github_sign_in', $githubUri); ?>
|
||||
</p>
|
||||
<?php endif; ?>
|
||||
<?php if (!empty($id)): ?>
|
||||
<?php if (empty($githubUser['name']) || empty($settings['phpci']['github']['token'])): ?>
|
||||
<p class="alert alert-warning clearfix">
|
||||
<?php Lang::out('github_sign_in', $githubUri); ?>
|
||||
</p>
|
||||
<?php else: ?>
|
||||
<p class="alert alert-success">
|
||||
<?php Lang::out('github_phpci_linked'); ?>
|
||||
|
||||
<?php if (!empty($id) && !empty($settings['phpci']['github']['token'])): ?>
|
||||
<p class="alert alert-success">
|
||||
<?php Lang::out('github_phpci_linked'); ?>
|
||||
|
||||
<strong>
|
||||
<a href="<?php echo $githubUser['html_url']; ?>"><?php echo $githubUser['name']; ?></a>
|
||||
</strong>
|
||||
</p>
|
||||
<strong>
|
||||
<a href="<?php echo $githubUser['html_url']; ?>"><?php echo $githubUser['name']; ?></a>
|
||||
</strong>
|
||||
</p>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -123,7 +123,7 @@ foreach($projects as $project):
|
|||
<i class="fa fa-<?php print $project->getIcon(); ?>"></i>
|
||||
</div>
|
||||
<a href="<?php print PHPCI_URL; ?>project/view/<?php print $project->getId(); ?>" class="small-box-footer small-box-footer-project">
|
||||
<?php Lang::out('view_project'); ?> <i class="fa fa-arrow-circle-right"></i>
|
||||
<?php Lang::out('view_project'); ?> (<?php print $counts[$project->getId()]; ?>) <i class="fa fa-arrow-circle-right"></i>
|
||||
</a>
|
||||
|
||||
<?php endif; ?>
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
<link href="<?php print PHPCI_URL; ?>assets/css/datepicker/datepicker3.css" rel="stylesheet" type="text/css" />
|
||||
<link href="<?php print PHPCI_URL; ?>assets/css/daterangepicker/daterangepicker-bs3.css" rel="stylesheet" type="text/css" />
|
||||
<link href="<?php print PHPCI_URL; ?>assets/css/ansi-colors.css" rel="stylesheet" type="text/css" />
|
||||
|
||||
<!-- Theme style -->
|
||||
<link href="<?php print PHPCI_URL; ?>assets/css/AdminLTE.css" rel="stylesheet" type="text/css" />
|
||||
|
@ -137,7 +138,7 @@
|
|||
|
||||
<!-- sidebar menu: : style can be found in sidebar.less -->
|
||||
<ul class="sidebar-menu">
|
||||
<li class="active">
|
||||
<li<?php print (array_key_exists('archived', $_GET) ? '' : ' class="active"'); ?>>
|
||||
<a href="<?php print PHPCI_URL; ?>">
|
||||
<i class="fa fa-dashboard"></i> <span><?php Lang::out('dashboard'); ?></span>
|
||||
</a>
|
||||
|
@ -237,8 +238,8 @@
|
|||
</li>
|
||||
<?php endif; ?>
|
||||
|
||||
<li class="archive">
|
||||
<a href="<?php print PHPCI_URL; ?>?archived">
|
||||
<li class="archive<?php print (array_key_exists('archived', $_GET) ? ' active' : ''); ?>">
|
||||
<a href="<?php print PHPCI_URL . (array_key_exists('archived', $_GET) ? '' : '?archived'); ?>">
|
||||
<i class="fa fa-archive"></i> <span><?php Lang::out('archived'); ?></span>
|
||||
</a>
|
||||
</li>
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* PHPCI - Continuous Integration for PHP
|
||||
*
|
||||
* @copyright Copyright 2014, Block 8 Limited.
|
||||
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
|
||||
* @link http://www.phptesting.org/
|
||||
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
|
||||
* @link https://www.phptesting.org/
|
||||
*/
|
||||
|
||||
namespace PHPCI\Plugin\Tests\Command;
|
||||
namespace Tests\PHPCI\Plugin\Command;
|
||||
|
||||
use Symfony\Component\Console\Application;
|
||||
use Symfony\Component\Console\Tester\CommandTester;
|
||||
|
@ -34,17 +35,17 @@ class CreateAdminCommandTest extends \PHPUnit_Framework_TestCase
|
|||
parent::setup();
|
||||
|
||||
$this->command = $this->getMockBuilder('PHPCI\\Command\\CreateAdminCommand')
|
||||
->setConstructorArgs([$this->getMock('PHPCI\\Store\\UserStore')])
|
||||
->setMethods(['reloadConfig'])
|
||||
->setConstructorArgs(array($this->getMock('PHPCI\\Store\\UserStore')))
|
||||
->setMethods(array('reloadConfig'))
|
||||
->getMock()
|
||||
;
|
||||
|
||||
$this->dialog = $this->getMockBuilder('Symfony\\Component\\Console\\Helper\\DialogHelper')
|
||||
->setMethods([
|
||||
->setMethods(array(
|
||||
'ask',
|
||||
'askAndValidate',
|
||||
'askHiddenResponse',
|
||||
])
|
||||
))
|
||||
->getMock()
|
||||
;
|
||||
|
||||
|
@ -71,7 +72,7 @@ class CreateAdminCommandTest extends \PHPUnit_Framework_TestCase
|
|||
$this->dialog->expects($this->at(2))->method('askHiddenResponse')->will($this->returnValue('foobar123'));
|
||||
|
||||
$commandTester = $this->getCommandTester();
|
||||
$commandTester->execute([]);
|
||||
$commandTester->execute(array());
|
||||
|
||||
$this->assertEquals('User account created!' . PHP_EOL, $commandTester->getDisplay());
|
||||
}
|
||||
|
|
86
Tests/PHPCI/Command/CreateBuildCommandTest.php
Normal file
86
Tests/PHPCI/Command/CreateBuildCommandTest.php
Normal file
|
@ -0,0 +1,86 @@
|
|||
<?php
|
||||
/**
|
||||
* PHPCI - Continuous Integration for PHP
|
||||
*
|
||||
* @copyright Copyright 2014, Block 8 Limited.
|
||||
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
|
||||
* @link http://www.phptesting.org/
|
||||
*/
|
||||
|
||||
namespace Tests\PHPCI\Command;
|
||||
|
||||
use Symfony\Component\Console\Application;
|
||||
use Symfony\Component\Console\Tester\CommandTester;
|
||||
|
||||
class CreateBuildCommandTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* @var \PHPCI\Command\CreateAdminCommand|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $command;
|
||||
|
||||
/**
|
||||
* @var \Symfony\Component\Console\Application|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $application;
|
||||
|
||||
public function setup()
|
||||
{
|
||||
parent::setup();
|
||||
|
||||
$projectMock = $this->getMock('PHPCI\\Model\\Project');
|
||||
|
||||
$projectStoreMock = $this->getMockBuilder('PHPCI\\Store\\ProjectStore')
|
||||
->getMock();
|
||||
$projectStoreMock->method('getById')
|
||||
->will($this->returnValueMap(array(
|
||||
array(1, 'read', $projectMock),
|
||||
array(2, 'read', null),
|
||||
)));
|
||||
|
||||
$buildServiceMock = $this->getMockBuilder('PHPCI\\Service\\BuildService')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$buildServiceMock->method('createBuild')
|
||||
->withConsecutive(
|
||||
array($projectMock, null, null, null, null, null),
|
||||
array($projectMock, '92c8c6e', null, null, null, null),
|
||||
array($projectMock, null, 'master', null, null, null)
|
||||
);
|
||||
|
||||
$this->command = $this->getMockBuilder('PHPCI\\Command\\CreateBuildCommand')
|
||||
->setConstructorArgs(array($projectStoreMock, $buildServiceMock))
|
||||
->setMethods(array('reloadConfig'))
|
||||
->getMock();
|
||||
|
||||
$this->application = new Application();
|
||||
}
|
||||
|
||||
protected function getCommandTester()
|
||||
{
|
||||
$this->application->add($this->command);
|
||||
|
||||
$command = $this->application->find('phpci:create-build');
|
||||
$commandTester = new CommandTester($command);
|
||||
|
||||
return $commandTester;
|
||||
}
|
||||
|
||||
public function testExecute()
|
||||
{
|
||||
$commandTester = $this->getCommandTester();
|
||||
|
||||
$commandTester->execute(array('projectId' => 1));
|
||||
$commandTester->execute(array('projectId' => 1, '--commit' => '92c8c6e'));
|
||||
$commandTester->execute(array('projectId' => 1, '--branch' => 'master'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testExecuteWithUnknowProjectId()
|
||||
{
|
||||
$commandTester = $this->getCommandTester();
|
||||
$commandTester->execute(array('projectId' => 2));
|
||||
}
|
||||
}
|
|
@ -1,16 +1,23 @@
|
|||
<?php
|
||||
|
||||
namespace PHPCI\Plugin\Tests\Command;
|
||||
/**
|
||||
* PHPCI - Continuous Integration for PHP
|
||||
*
|
||||
* @copyright Copyright 2015, Block 8 Limited.
|
||||
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
|
||||
* @link https://www.phptesting.org/
|
||||
*/
|
||||
|
||||
namespace Tests\PHPCI\Plugin\Command;
|
||||
|
||||
use Symfony\Component\Console\Application;
|
||||
use Prophecy\PhpUnit\ProphecyTestCase;
|
||||
use Symfony\Component\Console\Tester\CommandTester;
|
||||
use Symfony\Component\Console\Helper\HelperSet;
|
||||
|
||||
class InstallCommandTest extends ProphecyTestCase
|
||||
class InstallCommandTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
protected $config;
|
||||
protected $admin;
|
||||
public $config;
|
||||
public $admin;
|
||||
protected $application;
|
||||
|
||||
public function setup()
|
||||
|
@ -55,22 +62,26 @@ class InstallCommandTest extends ProphecyTestCase
|
|||
'setupDatabase',
|
||||
'createAdminUser',
|
||||
'writeConfigFile',
|
||||
'checkRequirements',
|
||||
))
|
||||
->getMock();
|
||||
|
||||
$self = $this;
|
||||
|
||||
$command->expects($this->once())->method('verifyNotInstalled')->willReturn(true);
|
||||
$command->expects($this->once())->method('verifyDatabaseDetails')->willReturn(true);
|
||||
$command->expects($this->once())->method('setupDatabase')->willReturn(true);
|
||||
$command->expects($this->once())->method('createAdminUser')->will(
|
||||
$this->returnCallback(function ($adm) {// use (&$admin) {
|
||||
$this->admin = $adm;
|
||||
$this->returnCallback(function ($adm) use ($self) {
|
||||
$self->admin = $adm;
|
||||
})
|
||||
);
|
||||
$command->expects($this->once())->method('writeConfigFile')->will(
|
||||
$this->returnCallback(function ($cfg) { //use (&$config) {
|
||||
$this->config = $cfg;
|
||||
$this->returnCallback(function ($cfg) use ($self) {
|
||||
$self->config = $cfg;
|
||||
})
|
||||
);
|
||||
$command->expects($this->once())->method('checkRequirements');
|
||||
|
||||
return $command;
|
||||
}
|
||||
|
|
41
Tests/PHPCI/Controller/WebhookControllerTest.php
Normal file
41
Tests/PHPCI/Controller/WebhookControllerTest.php
Normal file
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* 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/
|
||||
*/
|
||||
|
||||
namespace Tests\PHPCI\Controller;
|
||||
|
||||
use PHPCI\Controller\WebhookController;
|
||||
|
||||
class WebhookControllerTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function test_wrong_action_name_return_json_with_error()
|
||||
{
|
||||
$webController = new WebhookController(
|
||||
$this->prophesize('b8\Config')->reveal(),
|
||||
$this->prophesize('b8\Http\Request')->reveal(),
|
||||
$this->prophesize('b8\Http\Response')->reveal()
|
||||
);
|
||||
|
||||
$error = $webController->handleAction('test', []);
|
||||
|
||||
$this->assertInstanceOf('b8\Http\Response\JsonResponse', $error);
|
||||
|
||||
$responseData = $error->getData();
|
||||
$this->assertEquals(500, $responseData['code']);
|
||||
|
||||
$this->assertEquals('failed', $responseData['body']['status']);
|
||||
|
||||
$this->assertEquals('application/json', $responseData['headers']['Content-Type']);
|
||||
|
||||
// @todo: we can't text the result is JSON file with
|
||||
// $this->assertJson((string) $error);
|
||||
// since the flush method automatically add the header and break the
|
||||
// testing framework.
|
||||
}
|
||||
}
|
35
Tests/PHPCI/Helper/AnsiConverterTest.php
Normal file
35
Tests/PHPCI/Helper/AnsiConverterTest.php
Normal file
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* PHPCI - Continuous Integration for PHP
|
||||
*
|
||||
* @copyright Copyright 2015, Block 8 Limited.
|
||||
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
|
||||
* @link https://www.phptesting.org/
|
||||
*/
|
||||
|
||||
namespace Tests\PHPCI\Helper;
|
||||
|
||||
use PHPCI\Helper\AnsiConverter;
|
||||
use PHPUnit_Framework_TestCase;
|
||||
|
||||
class AnsiConverterTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function setUp()
|
||||
{
|
||||
if (version_compare(PHP_VERSION, '5.4.0', '<')) {
|
||||
$this->markTestSkipped('External library do not support PHP 5.3');
|
||||
}
|
||||
}
|
||||
|
||||
public function testConvert_convertToHtml()
|
||||
{
|
||||
$input = "\e[31mThis is red !\e[0m";
|
||||
|
||||
$expectedOutput = '<span class="ansi_color_bg_black ansi_color_fg_red">This is red !</span>';
|
||||
|
||||
$actualOutput = AnsiConverter::convert($input);
|
||||
|
||||
$this->assertEquals($expectedOutput, $actualOutput);
|
||||
}
|
||||
}
|
|
@ -1,11 +1,18 @@
|
|||
<?php
|
||||
|
||||
namespace PHPCI\Plugin\Tests\Helper;
|
||||
/**
|
||||
* PHPCI - Continuous Integration for PHP
|
||||
*
|
||||
* @copyright Copyright 2015, Block 8 Limited.
|
||||
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
|
||||
* @link https://www.phptesting.org/
|
||||
*/
|
||||
|
||||
namespace Tests\PHPCI\Plugin\Helper;
|
||||
|
||||
use PHPCI\Helper\BuildInterpolator;
|
||||
use Prophecy\PhpUnit\ProphecyTestCase;
|
||||
|
||||
class BuildInterpolatorTest extends ProphecyTestCase
|
||||
class BuildInterpolatorTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* @var BuildInterpolator
|
||||
|
@ -46,4 +53,4 @@ class BuildInterpolatorTest extends ProphecyTestCase
|
|||
$this->assertEquals($expectedOutput, $actualOutput);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,11 +1,18 @@
|
|||
<?php
|
||||
|
||||
namespace PHPCI\Plugin\Tests\Helper;
|
||||
/**
|
||||
* PHPCI - Continuous Integration for PHP
|
||||
*
|
||||
* @copyright Copyright 2015, Block 8 Limited.
|
||||
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
|
||||
* @link https://www.phptesting.org/
|
||||
*/
|
||||
|
||||
namespace Tests\PHPCI\Plugin\Helper;
|
||||
|
||||
use PHPCI\Helper\UnixCommandExecutor;
|
||||
use \Prophecy\PhpUnit\ProphecyTestCase;
|
||||
|
||||
class CommandExecutorTest extends ProphecyTestCase
|
||||
class CommandExecutorTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* @var UnixCommandExecutor
|
||||
|
@ -14,9 +21,14 @@ class CommandExecutorTest extends ProphecyTestCase
|
|||
|
||||
protected function setUp()
|
||||
{
|
||||
if (IS_WIN) {
|
||||
$this->markTestSkipped("Cannot test UnixCommandExecutor on ".PHP_OS);
|
||||
return;
|
||||
}
|
||||
parent::setUp();
|
||||
$mockBuildLogger = $this->prophesize('PHPCI\Logging\BuildLogger');
|
||||
$this->testedExecutor = new UnixCommandExecutor($mockBuildLogger->reveal(), __DIR__ . "/");
|
||||
$class = IS_WIN ? 'PHPCI\Helper\WindowsCommandExecutor' : 'PHPCI\Helper\UnixCommandExecutor';
|
||||
$this->testedExecutor = new $class($mockBuildLogger->reveal(), __DIR__ . "/");
|
||||
}
|
||||
|
||||
public function testGetLastOutput_ReturnsOutputOfCommand()
|
||||
|
@ -52,4 +64,20 @@ class CommandExecutorTest extends ProphecyTestCase
|
|||
$returnValue = $this->testedExecutor->findBinary($thisFileName);
|
||||
$this->assertEquals(__DIR__ . "/" . $thisFileName, $returnValue);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Exception
|
||||
* @expectedMessageRegex WorldWidePeace
|
||||
*/
|
||||
public function testFindBinary_ThrowsWhenNotFound()
|
||||
{
|
||||
$thisFileName = "WorldWidePeace";
|
||||
$this->testedExecutor->findBinary($thisFileName);
|
||||
}
|
||||
|
||||
public function testFindBinary_ReturnsNullWihQuietArgument()
|
||||
{
|
||||
$thisFileName = "WorldWidePeace";
|
||||
$this->assertNull($this->testedExecutor->findBinary($thisFileName, true));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,19 @@
|
|||
<?php
|
||||
|
||||
namespace PHPCI\Tests\Helper;
|
||||
/**
|
||||
* PHPCI - Continuous Integration for PHP
|
||||
*
|
||||
* @copyright Copyright 2015, Block 8 Limited.
|
||||
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
|
||||
* @link https://www.phptesting.org/
|
||||
*/
|
||||
|
||||
namespace Tests\PHPCI\Helper;
|
||||
|
||||
use DateTime;
|
||||
use PHPCI\Helper\Lang;
|
||||
use Prophecy\PhpUnit\ProphecyTestCase;
|
||||
|
||||
class LangTest extends ProphecyTestCase
|
||||
class LangTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testLang_UsePassedParameters()
|
||||
{
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* PHPCI - Continuous Integration for PHP
|
||||
*
|
||||
* @copyright Copyright 2014, Block 8 Limited.
|
||||
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
|
||||
* @link http://www.phptesting.org/
|
||||
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
|
||||
* @link https://www.phptesting.org/
|
||||
*/
|
||||
|
||||
namespace PHPCI\Service\Tests;
|
||||
namespace tests\PHPCI\Service;
|
||||
|
||||
use PHPCI\Helper\MailerFactory;
|
||||
|
||||
|
|
|
@ -1,13 +1,20 @@
|
|||
<?php
|
||||
|
||||
namespace PHPCI\Plugin\Tests\Helper;
|
||||
/**
|
||||
* PHPCI - Continuous Integration for PHP
|
||||
*
|
||||
* @copyright Copyright 2015, Block 8 Limited.
|
||||
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
|
||||
* @link https://www.phptesting.org/
|
||||
*/
|
||||
|
||||
namespace Tests\PHPCI\Plugin\Helper;
|
||||
|
||||
use PHPCI\Logging\BuildLogger;
|
||||
use Prophecy\Argument;
|
||||
use Prophecy\PhpUnit\ProphecyTestCase;
|
||||
use Psr\Log\LogLevel;
|
||||
|
||||
class BuildLoggerTest extends ProphecyTestCase
|
||||
class BuildLoggerTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* @var BuildLogger
|
||||
|
@ -104,4 +111,4 @@ class BuildLoggerTest extends ProphecyTestCase
|
|||
$this->testedBuildLogger->logFailure($message, $exception);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,14 @@
|
|||
<?php
|
||||
|
||||
namespace PHPCI\Plugin\Tests\Helper;
|
||||
/**
|
||||
* PHPCI - Continuous Integration for PHP
|
||||
*
|
||||
* @copyright Copyright 2015, Block 8 Limited.
|
||||
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
|
||||
* @link https://www.phptesting.org/
|
||||
*/
|
||||
|
||||
namespace Tests\PHPCI\Plugin\Helper;
|
||||
|
||||
use \PHPCI\Logging\LoggerConfig;
|
||||
|
||||
|
@ -73,5 +81,14 @@ class LoggerConfigTest extends \PHPUnit_Framework_TestCase
|
|||
$this->assertSame($expectedHandler, $actualHandler);
|
||||
$this->assertNotSame($alternativeHandler, $actualHandler);
|
||||
}
|
||||
|
||||
public function testGetFor_SameInstance()
|
||||
{
|
||||
$config = new LoggerConfig(array());
|
||||
|
||||
$logger1 = $config->getFor("something");
|
||||
$logger2 = $config->getFor("something");
|
||||
|
||||
$this->assertSame($logger1, $logger2);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,13 +1,15 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* PHPCI - Continuous Integration for PHP
|
||||
*
|
||||
* @copyright Copyright 2014, Block 8 Limited.
|
||||
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
|
||||
* @link http://www.phptesting.org/
|
||||
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
|
||||
* @link https://www.phptesting.org/
|
||||
*/
|
||||
|
||||
namespace PHPCI\Model\Tests;
|
||||
|
||||
namespace Tests\PHPCI\Model;
|
||||
|
||||
use PHPCI\Model\Build;
|
||||
use PHPCI\Model;
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* PHPCI - Continuous Integration for PHP
|
||||
*
|
||||
* @copyright Copyright 2014, Block 8 Limited.
|
||||
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
|
||||
* @link http://www.phptesting.org/
|
||||
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
|
||||
* @link https://www.phptesting.org/
|
||||
*/
|
||||
|
||||
namespace PHPCI\Model\Tests;
|
||||
|
||||
namespace Tests\PHPCI\Model;
|
||||
|
||||
use PHPCI\Model\Project;
|
||||
use PHPCI\Model;
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* PHPCI - Continuous Integration for PHP
|
||||
*
|
||||
* @copyright Copyright 2013, Block 8 Limited.
|
||||
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
|
||||
* @link http://www.phptesting.org/
|
||||
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
|
||||
* @link https://www.phptesting.org/
|
||||
*/
|
||||
|
||||
namespace PHPCI\Plugin\Tests;
|
||||
namespace Tests\PHPCI\Plugin;
|
||||
|
||||
use PHPCI\Plugin\Email as EmailPlugin;
|
||||
use PHPCI\Model\Build;
|
||||
|
@ -42,22 +43,23 @@ class EmailTest extends \PHPUnit_Framework_TestCase
|
|||
/**
|
||||
* @var int buildStatus
|
||||
*/
|
||||
protected $buildStatus;
|
||||
public $buildStatus;
|
||||
|
||||
/**
|
||||
* @var array $message;
|
||||
*/
|
||||
protected $message;
|
||||
public $message;
|
||||
|
||||
/**
|
||||
* @var bool $mailDelivered
|
||||
*/
|
||||
protected $mailDelivered;
|
||||
public $mailDelivered;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
$this->message = array();
|
||||
$this->mailDelivered = true;
|
||||
$self = $this;
|
||||
|
||||
$this->mockProject = $this->getMock(
|
||||
'\PHPCI\Model\Project',
|
||||
|
@ -85,8 +87,8 @@ class EmailTest extends \PHPUnit_Framework_TestCase
|
|||
|
||||
$this->mockBuild->expects($this->any())
|
||||
->method('getStatus')
|
||||
->will($this->returnCallback(function () {
|
||||
return $this->buildStatus;
|
||||
->will($this->returnCallback(function () use ($self) {
|
||||
return $self->buildStatus;
|
||||
}));
|
||||
|
||||
$this->mockBuild->expects($this->any())
|
||||
|
@ -138,6 +140,8 @@ class EmailTest extends \PHPUnit_Framework_TestCase
|
|||
// Reset current message.
|
||||
$this->message = array();
|
||||
|
||||
$self = $this;
|
||||
|
||||
$this->testedEmailPlugin = $this->getMock(
|
||||
'\PHPCI\Plugin\Email',
|
||||
array('sendEmail'),
|
||||
|
@ -150,13 +154,13 @@ class EmailTest extends \PHPUnit_Framework_TestCase
|
|||
|
||||
$this->testedEmailPlugin->expects($this->any())
|
||||
->method('sendEmail')
|
||||
->will($this->returnCallback(function ($to, $cc, $subject, $body) {
|
||||
$this->message['to'][] = $to;
|
||||
$this->message['cc'] = $cc;
|
||||
$this->message['subject'] = $subject;
|
||||
$this->message['body'] = $body;
|
||||
->will($this->returnCallback(function ($to, $cc, $subject, $body) use ($self) {
|
||||
$self->message['to'][] = $to;
|
||||
$self->message['cc'] = $cc;
|
||||
$self->message['subject'] = $subject;
|
||||
$self->message['body'] = $body;
|
||||
|
||||
return $this->mailDelivered;
|
||||
return $self->mailDelivered;
|
||||
}));
|
||||
}
|
||||
|
||||
|
@ -345,7 +349,7 @@ class EmailTest extends \PHPUnit_Framework_TestCase
|
|||
$this->testedEmailPlugin->execute();
|
||||
|
||||
$this->assertContains('Passing', $this->message['subject']);
|
||||
$this->assertContains('successfull', $this->message['body']);
|
||||
$this->assertContains('successful', $this->message['body']);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,5 +1,14 @@
|
|||
<?php
|
||||
namespace PHPCI\Plugin\Tests;
|
||||
|
||||
/**
|
||||
* PHPCI - Continuous Integration for PHP
|
||||
*
|
||||
* @copyright Copyright 2015, Block 8 Limited.
|
||||
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
|
||||
* @link https://www.phptesting.org/
|
||||
*/
|
||||
|
||||
namespace Tests\PHPCI\Plugin;
|
||||
|
||||
use PHPCI\Plugin\Phar as PharPlugin;
|
||||
use Phar as PHPPhar;
|
||||
|
@ -78,8 +87,7 @@ class PharTest extends \PHPUnit_Framework_TestCase
|
|||
protected function checkReadonly()
|
||||
{
|
||||
if (ini_get('phar.readonly')) {
|
||||
$this->markTestSkipped();
|
||||
throw new RuntimeException('Readonly Phar');
|
||||
$this->markTestSkipped('phar writing disabled in php.ini.');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,14 @@
|
|||
<?php
|
||||
|
||||
namespace PHPCI\Plugin\Tests\Util;
|
||||
/**
|
||||
* PHPCI - Continuous Integration for PHP
|
||||
*
|
||||
* @copyright Copyright 2015, Block 8 Limited.
|
||||
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
|
||||
* @link https://www.phptesting.org/
|
||||
*/
|
||||
|
||||
namespace Tests\PHPCI\Plugin\Util;
|
||||
|
||||
use PHPCI\Plugin\Util\ComposerPluginInformation;
|
||||
|
||||
|
@ -48,4 +56,4 @@ class ComposerPluginInformationTest extends \PHPUnit_Framework_TestCase
|
|||
$this->assertContainsOnly("string", $classes);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,4 +1,13 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* PHPCI - Continuous Integration for PHP
|
||||
*
|
||||
* @copyright Copyright 2015, Block 8 Limited.
|
||||
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
|
||||
* @link https://www.phptesting.org/
|
||||
*/
|
||||
|
||||
return function (PHPCI\Plugin\Util\Factory $factory) {
|
||||
$factory->registerResource(
|
||||
// This function will be called when the resource is needed.
|
||||
|
@ -10,4 +19,4 @@ return function (PHPCI\Plugin\Util\Factory $factory) {
|
|||
"requiredArgument",
|
||||
null
|
||||
);
|
||||
};
|
||||
};
|
||||
|
|
|
@ -1,78 +0,0 @@
|
|||
<?php
|
||||
namespace PHPCI\Plugin\Tests\Util;
|
||||
|
||||
use PHPCI\Builder;
|
||||
use PHPCI\Model\Build;
|
||||
use PHPCI\Plugin;
|
||||
|
||||
class ExamplePluginWithNoConstructorArgs implements Plugin
|
||||
{
|
||||
public function execute()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
class ExamplePluginWithSingleOptionalArg implements Plugin
|
||||
{
|
||||
function __construct($optional = null)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function execute()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class ExamplePluginWithSingleRequiredArg implements Plugin
|
||||
{
|
||||
|
||||
public $RequiredArgument;
|
||||
|
||||
function __construct($requiredArgument)
|
||||
{
|
||||
$this->RequiredArgument = $requiredArgument;
|
||||
}
|
||||
|
||||
public function execute()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class ExamplePluginWithSingleTypedRequiredArg implements Plugin
|
||||
{
|
||||
|
||||
public $RequiredArgument;
|
||||
|
||||
function __construct(\stdClass $requiredArgument)
|
||||
{
|
||||
$this->RequiredArgument = $requiredArgument;
|
||||
}
|
||||
|
||||
public function execute()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class ExamplePluginFull implements Plugin {
|
||||
|
||||
public $Options;
|
||||
|
||||
public function __construct(
|
||||
Builder $phpci,
|
||||
Build $build,
|
||||
array $options = array()
|
||||
)
|
||||
{
|
||||
$this->Options = $options;
|
||||
}
|
||||
|
||||
public function execute()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,14 +1,19 @@
|
|||
<?php
|
||||
|
||||
namespace PHPCI\Plugin\Tests\Util;
|
||||
/**
|
||||
* PHPCI - Continuous Integration for PHP
|
||||
*
|
||||
* @copyright Copyright 2015, Block 8 Limited.
|
||||
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
|
||||
* @link https://www.phptesting.org/
|
||||
*/
|
||||
|
||||
require_once __DIR__ . "/ExamplePlugins.php";
|
||||
namespace Tests\PHPCI\Plugin\Util;
|
||||
|
||||
use PHPCI\Plugin\Util\Executor;
|
||||
use Prophecy\Argument;
|
||||
use Prophecy\PhpUnit\ProphecyTestCase;
|
||||
|
||||
class ExecutorTest extends ProphecyTestCase
|
||||
class ExecutorTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* @var Executor
|
||||
|
@ -19,12 +24,19 @@ class ExecutorTest extends ProphecyTestCase
|
|||
|
||||
protected $mockFactory;
|
||||
|
||||
protected $mockStore;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
$this->mockBuildLogger = $this->prophesize('\PHPCI\Logging\BuildLogger');
|
||||
$this->mockFactory = $this->prophesize('\PHPCI\Plugin\Util\Factory');
|
||||
$this->testedExecutor = new Executor($this->mockFactory->reveal(), $this->mockBuildLogger->reveal());
|
||||
$this->mockStore = $this->prophesize('\PHPCI\Store\BuildStore');
|
||||
$this->testedExecutor = new Executor(
|
||||
$this->mockFactory->reveal(),
|
||||
$this->mockBuildLogger->reveal(),
|
||||
$this->mockStore->reveal()
|
||||
);
|
||||
}
|
||||
|
||||
public function testExecutePlugin_AssumesPHPCINamespaceIfNoneGiven()
|
||||
|
@ -43,25 +55,26 @@ class ExecutorTest extends ProphecyTestCase
|
|||
public function testExecutePlugin_KeepsCalledNameSpace()
|
||||
{
|
||||
$options = array();
|
||||
$pluginName = 'ExamplePluginFull';
|
||||
$pluginNamespace = '\\PHPCI\\Plugin\\Tests\\Util\\';
|
||||
$pluginClass = $this->getFakePluginClassName('ExamplePluginFull');
|
||||
|
||||
$this->mockFactory->buildPlugin($pluginNamespace . $pluginName, $options)
|
||||
$this->mockFactory->buildPlugin($pluginClass, $options)
|
||||
->shouldBeCalledTimes(1)
|
||||
->willReturn($this->prophesize('PHPCI\Plugin')->reveal());
|
||||
|
||||
$this->testedExecutor->executePlugin($pluginNamespace . $pluginName, $options);
|
||||
$this->testedExecutor->executePlugin($pluginClass, $options);
|
||||
}
|
||||
|
||||
public function testExecutePlugin_CallsExecuteOnFactoryBuildPlugin()
|
||||
{
|
||||
$options = array();
|
||||
$pluginName = 'PhpUnit';
|
||||
$build = new \PHPCI\Model\Build();
|
||||
|
||||
$mockPlugin = $this->prophesize('PHPCI\Plugin');
|
||||
$mockPlugin->execute()->shouldBeCalledTimes(1);
|
||||
|
||||
$this->mockFactory->buildPlugin(Argument::any(), Argument::any())->willReturn($mockPlugin->reveal());
|
||||
$this->mockFactory->getResourceFor('PHPCI\Model\Build')->willReturn($build);
|
||||
|
||||
$this->testedExecutor->executePlugin($pluginName, $options);
|
||||
}
|
||||
|
@ -115,6 +128,7 @@ class ExecutorTest extends ProphecyTestCase
|
|||
{
|
||||
$phpUnitPluginOptions = array();
|
||||
$behatPluginOptions = array();
|
||||
$build = new \PHPCI\Model\Build();
|
||||
|
||||
$config = array(
|
||||
'stageOne' => array(
|
||||
|
@ -130,7 +144,7 @@ class ExecutorTest extends ProphecyTestCase
|
|||
|
||||
$this->mockFactory->buildPlugin($pluginNamespace . 'PhpUnit', $phpUnitPluginOptions)
|
||||
->willReturn($mockPhpUnitPlugin->reveal());
|
||||
|
||||
$this->mockFactory->getResourceFor('PHPCI\Model\Build')->willReturn($build);
|
||||
|
||||
$mockBehatPlugin = $this->prophesize('PHPCI\Plugin');
|
||||
$mockBehatPlugin->execute()->shouldBeCalledTimes(1)->willReturn(true);
|
||||
|
@ -138,9 +152,14 @@ class ExecutorTest extends ProphecyTestCase
|
|||
$this->mockFactory->buildPlugin($pluginNamespace . 'Behat', $behatPluginOptions)
|
||||
->willReturn($mockBehatPlugin->reveal());
|
||||
|
||||
|
||||
$this->testedExecutor->executePlugins($config, 'stageOne');
|
||||
}
|
||||
|
||||
protected function getFakePluginClassName($pluginName)
|
||||
{
|
||||
$pluginNamespace = '\\Tests\\PHPCI\\Plugin\\Util\\Fake\\';
|
||||
|
||||
return $pluginNamespace . $pluginName;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,8 +1,14 @@
|
|||
<?php
|
||||
|
||||
namespace PHPCI\Plugin\Tests\Util;
|
||||
/**
|
||||
* PHPCI - Continuous Integration for PHP
|
||||
*
|
||||
* @copyright Copyright 2015, Block 8 Limited.
|
||||
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
|
||||
* @link https://www.phptesting.org/
|
||||
*/
|
||||
|
||||
require_once __DIR__ . "/ExamplePlugins.php";
|
||||
namespace Tests\PHPCI\Plugin\Util;
|
||||
|
||||
use PHPCI\Plugin\Util\Factory;
|
||||
|
||||
|
@ -49,10 +55,9 @@ class FactoryTest extends \PHPUnit_Framework_TestCase {
|
|||
|
||||
public function testBuildPluginWorksWithConstructorlessPlugins()
|
||||
{
|
||||
$namespace = '\\PHPCI\\Plugin\\Tests\\Util\\';
|
||||
$expectedPluginClass = $namespace .'ExamplePluginWithNoConstructorArgs';
|
||||
$plugin = $this->testedFactory->buildPlugin($expectedPluginClass);
|
||||
$this->assertInstanceOf($expectedPluginClass, $plugin);
|
||||
$pluginClass = $this->getFakePluginClassName('ExamplePluginWithNoConstructorArgs');
|
||||
$plugin = $this->testedFactory->buildPlugin($pluginClass);
|
||||
$this->assertInstanceOf($pluginClass, $plugin);
|
||||
}
|
||||
|
||||
public function testBuildPluginFailsForNonPluginClasses()
|
||||
|
@ -63,10 +68,9 @@ class FactoryTest extends \PHPUnit_Framework_TestCase {
|
|||
|
||||
public function testBuildPluginWorksWithSingleOptionalArgConstructor()
|
||||
{
|
||||
$namespace = '\\PHPCI\\Plugin\\Tests\\Util\\';
|
||||
$expectedPluginClass = $namespace . 'ExamplePluginWithSingleOptionalArg';
|
||||
$plugin = $this->testedFactory->buildPlugin($expectedPluginClass);
|
||||
$this->assertInstanceOf($expectedPluginClass, $plugin);
|
||||
$pluginClass = $this->getFakePluginClassName('ExamplePluginWithSingleOptionalArg');
|
||||
$plugin = $this->testedFactory->buildPlugin($pluginClass);
|
||||
$this->assertInstanceOf($pluginClass, $plugin);
|
||||
}
|
||||
|
||||
public function testBuildPluginThrowsExceptionIfMissingResourcesForRequiredArg()
|
||||
|
@ -76,15 +80,13 @@ class FactoryTest extends \PHPUnit_Framework_TestCase {
|
|||
'Unsatisfied dependency: requiredArgument'
|
||||
);
|
||||
|
||||
$namespace = '\\PHPCI\\Plugin\\Tests\\Util\\';
|
||||
$expectedPluginClass = $namespace . 'ExamplePluginWithSingleRequiredArg';
|
||||
$plugin = $this->testedFactory->buildPlugin($expectedPluginClass);
|
||||
$pluginClass = $this->getFakePluginClassName('ExamplePluginWithSingleRequiredArg');
|
||||
$plugin = $this->testedFactory->buildPlugin($pluginClass);
|
||||
}
|
||||
|
||||
public function testBuildPluginLoadsArgumentsBasedOnName()
|
||||
{
|
||||
$namespace = '\\PHPCI\\Plugin\\Tests\\Util\\';
|
||||
$expectedPluginClass = $namespace . 'ExamplePluginWithSingleRequiredArg';
|
||||
$pluginClass = $this->getFakePluginClassName('ExamplePluginWithSingleRequiredArg');
|
||||
|
||||
$this->testedFactory->registerResource(
|
||||
$this->resourceLoader,
|
||||
|
@ -92,15 +94,14 @@ class FactoryTest extends \PHPUnit_Framework_TestCase {
|
|||
);
|
||||
|
||||
/** @var ExamplePluginWithSingleRequiredArg $plugin */
|
||||
$plugin = $this->testedFactory->buildPlugin($expectedPluginClass);
|
||||
$plugin = $this->testedFactory->buildPlugin($pluginClass);
|
||||
|
||||
$this->assertEquals($this->expectedResource, $plugin->RequiredArgument);
|
||||
}
|
||||
|
||||
public function testBuildPluginLoadsArgumentsBasedOnType()
|
||||
{
|
||||
$namespace = '\\PHPCI\\Plugin\\Tests\\Util\\';
|
||||
$expectedPluginClass = $namespace . 'ExamplePluginWithSingleTypedRequiredArg';
|
||||
$pluginClass = $this->getFakePluginClassName('ExamplePluginWithSingleTypedRequiredArg');
|
||||
|
||||
$this->testedFactory->registerResource(
|
||||
$this->resourceLoader,
|
||||
|
@ -109,28 +110,26 @@ class FactoryTest extends \PHPUnit_Framework_TestCase {
|
|||
);
|
||||
|
||||
/** @var ExamplePluginWithSingleTypedRequiredArg $plugin */
|
||||
$plugin = $this->testedFactory->buildPlugin($expectedPluginClass);
|
||||
$plugin = $this->testedFactory->buildPlugin($pluginClass);
|
||||
|
||||
$this->assertEquals($this->expectedResource, $plugin->RequiredArgument);
|
||||
}
|
||||
|
||||
public function testBuildPluginLoadsFullExample()
|
||||
{
|
||||
$namespace = '\\PHPCI\\Plugin\\Tests\\Util\\';
|
||||
$expectedPluginClass = $namespace . 'ExamplePluginFull';
|
||||
$pluginClass = $this->getFakePluginClassName('ExamplePluginFull');
|
||||
|
||||
$this->registerBuildAndBuilder();
|
||||
|
||||
/** @var ExamplePluginFull $plugin */
|
||||
$plugin = $this->testedFactory->buildPlugin($expectedPluginClass);
|
||||
$plugin = $this->testedFactory->buildPlugin($pluginClass);
|
||||
|
||||
$this->assertInstanceOf($expectedPluginClass, $plugin);
|
||||
$this->assertInstanceOf($pluginClass, $plugin);
|
||||
}
|
||||
|
||||
public function testBuildPluginLoadsFullExampleWithOptions()
|
||||
{
|
||||
$namespace = '\\PHPCI\\Plugin\\Tests\\Util\\';
|
||||
$expectedPluginClass = $namespace . 'ExamplePluginFull';
|
||||
$pluginClass = $this->getFakePluginClassName('ExamplePluginFull');
|
||||
|
||||
$expectedArgs = array(
|
||||
'thing' => "stuff"
|
||||
|
@ -140,7 +139,7 @@ class FactoryTest extends \PHPUnit_Framework_TestCase {
|
|||
|
||||
/** @var ExamplePluginFull $plugin */
|
||||
$plugin = $this->testedFactory->buildPlugin(
|
||||
$expectedPluginClass,
|
||||
$pluginClass,
|
||||
$expectedArgs
|
||||
);
|
||||
|
||||
|
@ -163,10 +162,8 @@ class FactoryTest extends \PHPUnit_Framework_TestCase {
|
|||
realpath(__DIR__ . "/ExamplePluginConfig.php")
|
||||
);
|
||||
|
||||
$namespace = '\\PHPCI\\Plugin\\Tests\\Util\\';
|
||||
$pluginName = $namespace . 'ExamplePluginWithSingleRequiredArg';
|
||||
|
||||
$plugin = $this->testedFactory->buildPlugin($pluginName);
|
||||
$pluginClass = $this->getFakePluginClassName('ExamplePluginWithSingleRequiredArg');
|
||||
$plugin = $this->testedFactory->buildPlugin($pluginClass);
|
||||
|
||||
// The Example config file defines an array as the resource.
|
||||
$this->assertEquals(
|
||||
|
@ -181,9 +178,11 @@ class FactoryTest extends \PHPUnit_Framework_TestCase {
|
|||
*/
|
||||
private function registerBuildAndBuilder()
|
||||
{
|
||||
$self = $this;
|
||||
|
||||
$this->testedFactory->registerResource(
|
||||
function () {
|
||||
return $this->getMock(
|
||||
function () use ($self) {
|
||||
return $self->getMock(
|
||||
'PHPCI\Builder',
|
||||
array(),
|
||||
array(),
|
||||
|
@ -196,8 +195,8 @@ class FactoryTest extends \PHPUnit_Framework_TestCase {
|
|||
);
|
||||
|
||||
$this->testedFactory->registerResource(
|
||||
function () {
|
||||
return $this->getMock(
|
||||
function () use ($self) {
|
||||
return $self->getMock(
|
||||
'PHPCI\Model\Build',
|
||||
array(),
|
||||
array(),
|
||||
|
@ -206,8 +205,15 @@ class FactoryTest extends \PHPUnit_Framework_TestCase {
|
|||
);
|
||||
},
|
||||
null,
|
||||
'PHPCI\\Model\Build'
|
||||
'PHPCI\\Model\\Build'
|
||||
);
|
||||
}
|
||||
|
||||
protected function getFakePluginClassName($pluginName)
|
||||
{
|
||||
$pluginNamespace = '\\Tests\\PHPCI\\Plugin\\Util\\Fake\\';
|
||||
|
||||
return $pluginNamespace . $pluginName;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
36
Tests/PHPCI/Plugin/Util/Fake/ExamplePluginFull.php
Normal file
36
Tests/PHPCI/Plugin/Util/Fake/ExamplePluginFull.php
Normal file
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* PHPCI - Continuous Integration for PHP
|
||||
*
|
||||
* @copyright Copyright 2015, Block 8 Limited.
|
||||
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
|
||||
* @link https://www.phptesting.org/
|
||||
*/
|
||||
|
||||
namespace Tests\PHPCI\Plugin\Util\Fake;
|
||||
|
||||
use PHPCI\Builder;
|
||||
use PHPCI\Model\Build;
|
||||
use PHPCI\Plugin;
|
||||
|
||||
class ExamplePluginFull implements Plugin {
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
public $Options;
|
||||
|
||||
public function __construct(
|
||||
Builder $phpci,
|
||||
Build $build,
|
||||
array $options = array()
|
||||
)
|
||||
{
|
||||
$this->Options = $options;
|
||||
}
|
||||
|
||||
public function execute()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue