Merge branch 'github-improvements'
This commit is contained in:
commit
dcc1ff9073
|
@ -374,10 +374,22 @@ class ProjectController extends WebController
|
||||||
$values['pubkey'] = $values['ssh_public_key'];
|
$values['pubkey'] = $values['ssh_public_key'];
|
||||||
$values['environments'] = $project->getEnvironments();
|
$values['environments'] = $project->getEnvironments();
|
||||||
|
|
||||||
if (Project::TYPE_GITLAB === $values['type']) {
|
if (in_array($values['type'], [
|
||||||
$accessInfo = $project->getAccessInformation();
|
Project::TYPE_GITHUB,
|
||||||
$reference = $accessInfo["user"] . '@' . $accessInfo["domain"] . ':' . $accessInfo["port"] . '/' . ltrim($project->getReference(), '/') . ".git";
|
Project::TYPE_GITLAB
|
||||||
$values['reference'] = $reference;
|
], true)) {
|
||||||
|
$originReference = $project->getAccessInformation('origin');
|
||||||
|
if ($originReference) {
|
||||||
|
$values['reference'] = $originReference;
|
||||||
|
} else {
|
||||||
|
$accessInfo = $project->getAccessInformation();
|
||||||
|
$reference = $accessInfo['user'] . '@' . $accessInfo['domain'] . ':' . ltrim($project->getReference(), '/') . '.git';
|
||||||
|
if (isset($accessInfo['port']) && $accessInfo['port']) {
|
||||||
|
$reference = $accessInfo['user'] . '@' . $accessInfo['domain'] . ':' . $accessInfo['port'] . '/' . ltrim($project->getReference(), '/') . '.git';
|
||||||
|
}
|
||||||
|
|
||||||
|
$values['reference'] = $reference;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($method == 'POST') {
|
if ($method == 'POST') {
|
||||||
|
@ -535,7 +547,8 @@ class ProjectController extends WebController
|
||||||
protected function getReferenceValidator($values)
|
protected function getReferenceValidator($values)
|
||||||
{
|
{
|
||||||
return function ($val) use ($values) {
|
return function ($val) use ($values) {
|
||||||
$type = $values['type'];
|
$type = $values['type'];
|
||||||
|
$gitRegex = '#^((https|http|ssh)://)?((.+)@)?(([^/:]+):?)(:?([0-9]*)/?)(.+)\.git#';
|
||||||
|
|
||||||
$validators = [
|
$validators = [
|
||||||
Project::TYPE_HG => [
|
Project::TYPE_HG => [
|
||||||
|
@ -543,19 +556,19 @@ class ProjectController extends WebController
|
||||||
'message' => Lang::get('error_hg')
|
'message' => Lang::get('error_hg')
|
||||||
],
|
],
|
||||||
Project::TYPE_GIT => [
|
Project::TYPE_GIT => [
|
||||||
'regex' => '/^(git|https?):\/\//',
|
'regex' => $gitRegex,
|
||||||
'message' => Lang::get('error_git')
|
'message' => Lang::get('error_git')
|
||||||
],
|
],
|
||||||
Project::TYPE_GITLAB => [
|
Project::TYPE_GITLAB => [
|
||||||
'regex' => '/^(git|https?):\/\//',
|
'regex' => $gitRegex,
|
||||||
'message' => Lang::get('error_gitlab')
|
'message' => Lang::get('error_gitlab')
|
||||||
],
|
],
|
||||||
Project::TYPE_GITHUB => [
|
Project::TYPE_GITHUB => [
|
||||||
'regex' => '/^(git|https?):\/\//',
|
'regex' => $gitRegex,
|
||||||
'message' => Lang::get('error_github')
|
'message' => Lang::get('error_github')
|
||||||
],
|
],
|
||||||
Project::TYPE_BITBUCKET => [
|
Project::TYPE_BITBUCKET => [
|
||||||
'regex' => '/^[a-zA-Z0-9_\-]+\/[a-zA-Z0-9_\-\.]+$/',
|
'regex' => $gitRegex,
|
||||||
'message' => Lang::get('error_bitbucket')
|
'message' => Lang::get('error_bitbucket')
|
||||||
],
|
],
|
||||||
Project::TYPE_BITBUCKET_HG => [
|
Project::TYPE_BITBUCKET_HG => [
|
||||||
|
|
|
@ -4,98 +4,12 @@ namespace PHPCensor\Helper;
|
||||||
|
|
||||||
use PHPCensor\Config;
|
use PHPCensor\Config;
|
||||||
use GuzzleHttp\Client;
|
use GuzzleHttp\Client;
|
||||||
use Symfony\Component\Cache\Simple\FilesystemCache;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Github Helper class provides some Github API call functionality.
|
* The Github Helper class provides some Github API call functionality.
|
||||||
*/
|
*/
|
||||||
class Github
|
class Github
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* Make all GitHub requests following the Link HTTP headers.
|
|
||||||
*
|
|
||||||
* @param string $url
|
|
||||||
* @param mixed $params
|
|
||||||
* @param array $results
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function makeRecursiveRequest($url, $params, $results = [])
|
|
||||||
{
|
|
||||||
$client = new Client();
|
|
||||||
$response = $client->get(('https://api.github.com' . $url), [
|
|
||||||
'query' => $params,
|
|
||||||
]);
|
|
||||||
|
|
||||||
$body = json_decode($response->getBody(), true);
|
|
||||||
$headers = $response->getHeaders();
|
|
||||||
|
|
||||||
foreach ($body as $item) {
|
|
||||||
$results[] = $item;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($headers as $headerName => $header) {
|
|
||||||
if (
|
|
||||||
'Link' === $headerName &&
|
|
||||||
preg_match('/^<([^>]+)>; rel="next"/', implode(', ', $header), $r)
|
|
||||||
) {
|
|
||||||
$host = parse_url($r[1]);
|
|
||||||
|
|
||||||
parse_str($host['query'], $params);
|
|
||||||
$results = $this->makeRecursiveRequest($host['path'], $params, $results);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $results;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get an array of repositories from Github's API.
|
|
||||||
*/
|
|
||||||
public function getRepositories()
|
|
||||||
{
|
|
||||||
$token = Config::getInstance()->get('php-censor.github.token');
|
|
||||||
|
|
||||||
if (!$token) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
$cache = new FilesystemCache('', 0, RUNTIME_DIR . 'cache');
|
|
||||||
$rtn = $cache->get('php-censor.github-repos');
|
|
||||||
|
|
||||||
if (!$rtn) {
|
|
||||||
$client = new Client();
|
|
||||||
$response = $client->get('https://api.github.com/user/orgs', [
|
|
||||||
'query' => [
|
|
||||||
'access_token' => $token
|
|
||||||
],
|
|
||||||
]);
|
|
||||||
|
|
||||||
$orgs = json_decode($response->getBody(), true);
|
|
||||||
|
|
||||||
$params = ['type' => 'all', 'access_token' => $token];
|
|
||||||
$repos = ['user' => []];
|
|
||||||
$repos['user'] = $this->makeRecursiveRequest('/user/repos', $params);
|
|
||||||
|
|
||||||
foreach ($orgs as $org) {
|
|
||||||
$repos[$org['login']] = $this->makeRecursiveRequest('/orgs/' . $org['login'] . '/repos', $params);
|
|
||||||
}
|
|
||||||
|
|
||||||
$rtn = [];
|
|
||||||
foreach ($repos as $repoGroup) {
|
|
||||||
foreach ($repoGroup as $repo) {
|
|
||||||
$rtn['repos'][] = $repo['full_name'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$cache->set('php-censor.github-repos', $rtn, 3600);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $rtn;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a comment on a specific file (and commit) in a Github Pull Request.
|
* Create a comment on a specific file (and commit) in a Github Pull Request.
|
||||||
* @param $repo
|
* @param $repo
|
||||||
|
|
|
@ -49,8 +49,8 @@ class GitlabBuild extends GitBuild
|
||||||
$key = trim($this->getProject()->getSshPrivateKey());
|
$key = trim($this->getProject()->getSshPrivateKey());
|
||||||
|
|
||||||
if (!empty($key)) {
|
if (!empty($key)) {
|
||||||
$user = $this->getProject()->getAccessInformation("user");
|
$user = $this->getProject()->getAccessInformation('user');
|
||||||
$domain = $this->getProject()->getAccessInformation("domain");
|
$domain = $this->getProject()->getAccessInformation('domain');
|
||||||
$port = $this->getProject()->getAccessInformation('port');
|
$port = $this->getProject()->getAccessInformation('port');
|
||||||
|
|
||||||
$url = $user . '@' . $domain . ':';
|
$url = $user . '@' . $domain . ':';
|
||||||
|
|
|
@ -143,7 +143,6 @@ class ProjectService
|
||||||
*/
|
*/
|
||||||
protected function processAccessInformation(Project $project)
|
protected function processAccessInformation(Project $project)
|
||||||
{
|
{
|
||||||
$matches = [];
|
|
||||||
$reference = $project->getReference();
|
$reference = $project->getReference();
|
||||||
|
|
||||||
if (in_array($project->getType(), [
|
if (in_array($project->getType(), [
|
||||||
|
@ -152,12 +151,30 @@ class ProjectService
|
||||||
], true)) {
|
], true)) {
|
||||||
$info = [];
|
$info = [];
|
||||||
|
|
||||||
if (preg_match('`^(.+)@(.+):([0-9]*)\/?(.+)\.git`', $reference, $matches)) {
|
if (preg_match(
|
||||||
$info['user'] = $matches[1];
|
'#^((https|http|ssh)://)?((.+)@)?(([^/:]+):?)(:?([0-9]*)/?)(.+)\.git#',
|
||||||
$info['domain'] = $matches[2];
|
$reference,
|
||||||
$info['port'] = $matches[3];
|
$matches
|
||||||
|
)) {
|
||||||
|
if (isset($matches[4]) && $matches[4]) {
|
||||||
|
$info['user'] = $matches[4];
|
||||||
|
}
|
||||||
|
|
||||||
$project->setReference($matches[4]);
|
if (isset($matches[6]) && $matches[6]) {
|
||||||
|
$info['domain'] = $matches[6];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($matches[8]) && $matches[8]) {
|
||||||
|
$info['port'] = $matches[8];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($matches[9]) && $matches[9]) {
|
||||||
|
$info['reference'] = $matches[9];
|
||||||
|
|
||||||
|
$project->setReference($matches[9]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$info['origin'] = $reference;
|
||||||
}
|
}
|
||||||
|
|
||||||
$project->setAccessInformation($info);
|
$project->setAccessInformation($info);
|
||||||
|
|
|
@ -25,25 +25,184 @@ class ProjectServiceTest extends \PHPUnit\Framework\TestCase
|
||||||
|
|
||||||
public function setUp()
|
public function setUp()
|
||||||
{
|
{
|
||||||
$this->mockProjectStore = $this->getMockBuilder('PHPCensor\Store\ProjectStore')->getMock();
|
$this->mockProjectStore = $this
|
||||||
$this->mockProjectStore->expects($this->any())
|
->getMockBuilder('PHPCensor\Store\ProjectStore')
|
||||||
->method('save')
|
->getMock();
|
||||||
->will($this->returnArgument(0));
|
|
||||||
|
$this->mockProjectStore
|
||||||
|
->expects($this->any())
|
||||||
|
->method('save')
|
||||||
|
->will(
|
||||||
|
$this->returnArgument(0)
|
||||||
|
);
|
||||||
|
|
||||||
$this->testedService = new ProjectService($this->mockProjectStore);
|
$this->testedService = new ProjectService($this->mockProjectStore);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testExecute_CreateBasicProject()
|
public function testExecuteCreateGithubProject()
|
||||||
{
|
{
|
||||||
$returnValue = $this->testedService->createProject('Test Project', 'github', 'block8/phpci', 0);
|
$project = $this->testedService->createProject(
|
||||||
|
'Test Project',
|
||||||
|
'github',
|
||||||
|
'php-censor/php-censor1',
|
||||||
|
0
|
||||||
|
);
|
||||||
|
|
||||||
self::assertEquals('Test Project', $returnValue->getTitle());
|
self::assertEquals('Test Project', $project->getTitle());
|
||||||
self::assertEquals('github', $returnValue->getType());
|
self::assertEquals('github', $project->getType());
|
||||||
self::assertEquals('block8/phpci', $returnValue->getReference());
|
self::assertEquals('php-censor/php-censor1', $project->getReference());
|
||||||
self::assertEquals('master', $returnValue->getBranch());
|
self::assertEquals('master', $project->getBranch());
|
||||||
|
self::assertEquals([], $project->getAccessInformation());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testExecute_CreateProjectWithOptions()
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getExecuteCreateGithubProjectAccessInformationData()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
[
|
||||||
|
'git@github.com:php-censor/php-censor.git', [
|
||||||
|
'user' => 'git',
|
||||||
|
'domain' => 'github.com',
|
||||||
|
'reference' => 'php-censor/php-censor',
|
||||||
|
'origin' => 'git@github.com:php-censor/php-censor.git',
|
||||||
|
],
|
||||||
|
], [
|
||||||
|
'git@sss.github.com:php-censor/php-censor.git', [
|
||||||
|
'user' => 'git',
|
||||||
|
'domain' => 'sss.github.com',
|
||||||
|
'reference' => 'php-censor/php-censor',
|
||||||
|
'origin' => 'git@sss.github.com:php-censor/php-censor.git',
|
||||||
|
],
|
||||||
|
], [
|
||||||
|
'ssh://git@github.com/php-censor/php-censor.git', [
|
||||||
|
'user' => 'git',
|
||||||
|
'domain' => 'github.com',
|
||||||
|
'reference' => 'php-censor/php-censor',
|
||||||
|
'origin' => 'ssh://git@github.com/php-censor/php-censor.git',
|
||||||
|
],
|
||||||
|
], [
|
||||||
|
'https://github.com/php-censor/php-censor.git', [
|
||||||
|
'domain' => 'github.com',
|
||||||
|
'reference' => 'php-censor/php-censor',
|
||||||
|
'origin' => 'https://github.com/php-censor/php-censor.git',
|
||||||
|
],
|
||||||
|
], [
|
||||||
|
'http://github.com/php-censor/php-censor.git', [
|
||||||
|
'domain' => 'github.com',
|
||||||
|
'reference' => 'php-censor/php-censor',
|
||||||
|
'origin' => 'http://github.com/php-censor/php-censor.git',
|
||||||
|
],
|
||||||
|
], [
|
||||||
|
'git@github.com:443/php-censor/php-censor.git', [
|
||||||
|
'user' => 'git',
|
||||||
|
'domain' => 'github.com',
|
||||||
|
'port' => '443',
|
||||||
|
'reference' => 'php-censor/php-censor',
|
||||||
|
'origin' => 'git@github.com:443/php-censor/php-censor.git',
|
||||||
|
],
|
||||||
|
], [
|
||||||
|
'ssh://git@github.com:443/php-censor/php-censor.git', [
|
||||||
|
'user' => 'git',
|
||||||
|
'domain' => 'github.com',
|
||||||
|
'port' => '443',
|
||||||
|
'reference' => 'php-censor/php-censor',
|
||||||
|
'origin' => 'ssh://git@github.com:443/php-censor/php-censor.git',
|
||||||
|
],
|
||||||
|
], [
|
||||||
|
'https://github.com:443/php-censor/php-censor.git', [
|
||||||
|
'domain' => 'github.com',
|
||||||
|
'port' => '443',
|
||||||
|
'reference' => 'php-censor/php-censor',
|
||||||
|
'origin' => 'https://github.com:443/php-censor/php-censor.git',
|
||||||
|
],
|
||||||
|
], [
|
||||||
|
'http://github.com:443/php-censor/php-censor.git', [
|
||||||
|
'domain' => 'github.com',
|
||||||
|
'port' => '443',
|
||||||
|
'reference' => 'php-censor/php-censor',
|
||||||
|
'origin' => 'http://github.com:443/php-censor/php-censor.git',
|
||||||
|
],
|
||||||
|
], [
|
||||||
|
'git@github:php-censor.git', [
|
||||||
|
'user' => 'git',
|
||||||
|
'domain' => 'github',
|
||||||
|
'reference' => 'php-censor',
|
||||||
|
'origin' => 'git@github:php-censor.git',
|
||||||
|
],
|
||||||
|
], [
|
||||||
|
'ssh://git@github/php-censor.git', [
|
||||||
|
'user' => 'git',
|
||||||
|
'domain' => 'github',
|
||||||
|
'reference' => 'php-censor',
|
||||||
|
'origin' => 'ssh://git@github/php-censor.git',
|
||||||
|
],
|
||||||
|
], [
|
||||||
|
'https://github/php-censor.git', [
|
||||||
|
'domain' => 'github',
|
||||||
|
'reference' => 'php-censor',
|
||||||
|
'origin' => 'https://github/php-censor.git',
|
||||||
|
],
|
||||||
|
], [
|
||||||
|
'http://github/php-censor.git', [
|
||||||
|
'domain' => 'github',
|
||||||
|
'reference' => 'php-censor',
|
||||||
|
'origin' => 'http://github/php-censor.git',
|
||||||
|
],
|
||||||
|
], [
|
||||||
|
'git@github:443/php-censor.git', [
|
||||||
|
'user' => 'git',
|
||||||
|
'domain' => 'github',
|
||||||
|
'port' => '443',
|
||||||
|
'reference' => 'php-censor',
|
||||||
|
'origin' => 'git@github:443/php-censor.git',
|
||||||
|
],
|
||||||
|
], [
|
||||||
|
'ssh://git@github:443/php-censor.git', [
|
||||||
|
'user' => 'git',
|
||||||
|
'domain' => 'github',
|
||||||
|
'port' => '443',
|
||||||
|
'reference' => 'php-censor',
|
||||||
|
'origin' => 'ssh://git@github:443/php-censor.git',
|
||||||
|
],
|
||||||
|
], [
|
||||||
|
'https://github:443/php-censor.git', [
|
||||||
|
'domain' => 'github',
|
||||||
|
'port' => '443',
|
||||||
|
'reference' => 'php-censor',
|
||||||
|
'origin' => 'https://github:443/php-censor.git',
|
||||||
|
],
|
||||||
|
], [
|
||||||
|
'http://github:443/php-censor.git', [
|
||||||
|
'domain' => 'github',
|
||||||
|
'port' => '443',
|
||||||
|
'reference' => 'php-censor',
|
||||||
|
'origin' => 'http://github:443/php-censor.git',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $reference
|
||||||
|
* @param array $accessInformation
|
||||||
|
*
|
||||||
|
* @dataProvider getExecuteCreateGithubProjectAccessInformationData
|
||||||
|
*/
|
||||||
|
public function testExecuteCreateGithubProjectAccessInformation($reference, array $accessInformation)
|
||||||
|
{
|
||||||
|
$project = $this->testedService->createProject(
|
||||||
|
'Test Project',
|
||||||
|
'github',
|
||||||
|
$reference,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
|
||||||
|
self::assertEquals($accessInformation, $project->getAccessInformation());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testExecuteCreateProjectWithOptions()
|
||||||
{
|
{
|
||||||
$options = [
|
$options = [
|
||||||
'ssh_private_key' => 'private',
|
'ssh_private_key' => 'private',
|
||||||
|
@ -53,7 +212,13 @@ class ProjectServiceTest extends \PHPUnit\Framework\TestCase
|
||||||
'branch' => 'testbranch',
|
'branch' => 'testbranch',
|
||||||
];
|
];
|
||||||
|
|
||||||
$returnValue = $this->testedService->createProject('Test Project', 'github', 'block8/phpci', 0, $options);
|
$returnValue = $this->testedService->createProject(
|
||||||
|
'Test Project',
|
||||||
|
'github',
|
||||||
|
'block8/phpci',
|
||||||
|
0,
|
||||||
|
$options
|
||||||
|
);
|
||||||
|
|
||||||
self::assertEquals('private', $returnValue->getSshPrivateKey());
|
self::assertEquals('private', $returnValue->getSshPrivateKey());
|
||||||
self::assertEquals('public', $returnValue->getSshPublicKey());
|
self::assertEquals('public', $returnValue->getSshPublicKey());
|
||||||
|
@ -62,25 +227,7 @@ class ProjectServiceTest extends \PHPUnit\Framework\TestCase
|
||||||
self::assertEquals(true, $returnValue->getAllowPublicStatus());
|
self::assertEquals(true, $returnValue->getAllowPublicStatus());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function testExecuteUpdateExistingProject()
|
||||||
* @link https://github.com/Block8/PHPCI/issues/484
|
|
||||||
*/
|
|
||||||
public function testExecute_CreateGitlabProjectWithoutPort()
|
|
||||||
{
|
|
||||||
$reference = 'git@gitlab.block8.net:block8/phpci.git';
|
|
||||||
$returnValue = $this->testedService->createProject(
|
|
||||||
'Gitlab',
|
|
||||||
Project::TYPE_GITLAB,
|
|
||||||
$reference,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
|
|
||||||
self::assertEquals('git', $returnValue->getAccessInformation('user'));
|
|
||||||
self::assertEquals('gitlab.block8.net', $returnValue->getAccessInformation('domain'));
|
|
||||||
self::assertEquals('block8/phpci', $returnValue->getReference());
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testExecute_UpdateExistingProject()
|
|
||||||
{
|
{
|
||||||
$project = new Project();
|
$project = new Project();
|
||||||
$project->setTitle('Before Title');
|
$project->setTitle('Before Title');
|
||||||
|
@ -94,7 +241,7 @@ class ProjectServiceTest extends \PHPUnit\Framework\TestCase
|
||||||
self::assertEquals('bitbucket', $returnValue->getType());
|
self::assertEquals('bitbucket', $returnValue->getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testExecute_EmptyPublicStatus()
|
public function testExecuteEmptyPublicStatus()
|
||||||
{
|
{
|
||||||
$project = new Project();
|
$project = new Project();
|
||||||
$project->setAllowPublicStatus(true);
|
$project->setAllowPublicStatus(true);
|
||||||
|
@ -110,7 +257,7 @@ class ProjectServiceTest extends \PHPUnit\Framework\TestCase
|
||||||
self::assertEquals(false, $returnValue->getAllowPublicStatus());
|
self::assertEquals(false, $returnValue->getAllowPublicStatus());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testExecute_DeleteProject()
|
public function testExecuteDeleteProject()
|
||||||
{
|
{
|
||||||
$store = $this->getMockBuilder('PHPCensor\Store\ProjectStore')->getMock();
|
$store = $this->getMockBuilder('PHPCensor\Store\ProjectStore')->getMock();
|
||||||
$store->expects($this->once())
|
$store->expects($this->once())
|
||||||
|
|
Loading…
Reference in a new issue