From dfeac39be3f2bfc78c51eaae98a0e3573e1378f8 Mon Sep 17 00:00:00 2001 From: Dan Cryer Date: Tue, 14 May 2013 16:37:54 +0100 Subject: [PATCH 1/4] Github integration. --- PHPCI/Controller/ProjectController.php | 79 ++++++++++++++++++++------ PHPCI/View/ProjectForm.phtml | 59 ++++++++++++++++++- 2 files changed, 121 insertions(+), 17 deletions(-) diff --git a/PHPCI/Controller/ProjectController.php b/PHPCI/Controller/ProjectController.php index d0834df8..f39c511c 100644 --- a/PHPCI/Controller/ProjectController.php +++ b/PHPCI/Controller/ProjectController.php @@ -94,18 +94,34 @@ class ProjectController extends b8\Controller $pub = file_get_contents($id . '.pub'); $prv = file_get_contents($id); - $values = array('key' => $prv); + $values = array('key' => $prv, 'pubkey' => $pub); } $form = $this->projectForm($values); if($method != 'POST' || ($method == 'POST' && !$form->validate())) { + $gh = \b8\Registry::getInstance()->get('github_app'); + $code = $this->getParam('code', null); + + if(!is_null($code)) + { + $http = new \b8\HttpClient(); + $resp = $http->post('https://github.com/login/oauth/access_token', array('client_id' => $gh['id'], 'client_secret' => $gh['secret'], 'code' => $code)); + + if($resp['success']) + { + parse_str($resp['body'], $resp); + $_SESSION['github_token'] = $resp['access_token']; + } + } + $view = new b8\View('ProjectForm'); $view->type = 'add'; $view->project = null; $view->form = $form; $view->key = $pub; + $view->token = $_SESSION['github_token'] ? $_SESSION['github_token'] : null; return $view->render(); } @@ -171,27 +187,40 @@ class ProjectController extends b8\Controller $form->setMethod('POST'); $form->setAction('/project/' . $type); $form->addField(new Form\Element\Csrf('csrf')); + $form->addField(new Form\Element\Hidden('token')); + $form->addField(new Form\Element\Hidden('pubkey')); + + $field = new Form\Element\Select('type'); + $field->setRequired(true); + $field->setPattern('^(github|bitbucket)'); + $field->setOptions(array('choose' => 'Select repository type...', 'github' => 'Github', 'bitbucket' => 'Bitbucket')); + $field->setLabel('Where is your project hosted?'); + $field->setClass('span4'); + $form->addField($field); + + if(isset($_SESSION['github_token'])) + { + $field = new Form\Element\Select('github'); + $field->setPattern('[a-zA-Z0-9_\-]+\/[a-zA-Z0-9_\-]+'); + $field->setLabel('Choose a Github repository:'); + $field->setClass('span4'); + $field->setOptions($this->getGithubRepositories()); + $form->addField($field); + } + + $field = new Form\Element\Text('reference'); + $field->setRequired(true); + $field->setPattern('[a-zA-Z0-9_\-]+\/[a-zA-Z0-9_\-]+'); + $field->setLabel('Repository Name / URL:'); + $field->setClass('span4'); + $form->addField($field); $field = new Form\Element\Text('title'); $field->setRequired(true); $field->setLabel('Project Title'); $field->setClass('span4'); $form->addField($field); - - $field = new Form\Element\Select('type'); - $field->setRequired(true); - $field->setOptions(array('github' => 'Github', 'bitbucket' => 'Bitbucket')); - $field->setLabel('Where is your project hosted?'); - $field->setClass('span4'); - $form->addField($field); - - $field = new Form\Element\Text('reference'); - $field->setRequired(true); - $field->setPattern('[a-zA-Z0-9_\-]+\/[a-zA-Z0-9_\-]+'); - $field->setLabel('Repository Name on Github / Bitbucket (e.g. block8/phpci)'); - $field->setClass('span4'); - $form->addField($field); - + $field = new Form\Element\TextArea('key'); $field->setRequired(false); $field->setLabel('Private key to use to access repository (leave blank to use anonymous HTTP repository access)'); @@ -207,4 +236,22 @@ class ProjectController extends b8\Controller $form->setValues($values); return $form; } + + protected function getGithubRepositories() + { + $http = new \b8\HttpClient(); + $res = $http->get('https://api.github.com/user/repos', array('type' => 'all', 'access_token' => $_SESSION['github_token'])); + + $rtn = array(); + $rtn['choose'] = 'Select a repository...'; + if($res['success']) + { + foreach($res['body'] as $repo) + { + $rtn[$repo['full_name']] = $repo['full_name']; + } + } + + return $rtn; + } } \ No newline at end of file diff --git a/PHPCI/View/ProjectForm.phtml b/PHPCI/View/ProjectForm.phtml index d941af80..af1c7e43 100644 --- a/PHPCI/View/ProjectForm.phtml +++ b/PHPCI/View/ProjectForm.phtml @@ -23,6 +23,20 @@ \ No newline at end of file From 812dfcb95a5a9d94a7f79a8725927e2f9a0fad20 Mon Sep 17 00:00:00 2001 From: Dan Cryer Date: Tue, 14 May 2013 16:58:14 +0100 Subject: [PATCH 2/4] Github pull request status updates --- PHPCI/Builder.php | 2 ++ PHPCI/Controller/GithubController.php | 3 ++- PHPCI/Model/Base/ProjectBase.php | 33 ++++++++++++++++++++++++++ PHPCI/Model/Build.php | 34 +++++++++++++++++++++++++++ PHPCI/View/ProjectForm.phtml | 5 +--- install.php | 17 ++++++++++++-- 6 files changed, 87 insertions(+), 7 deletions(-) diff --git a/PHPCI/Builder.php b/PHPCI/Builder.php index 7c3c1dc1..f6e926d6 100644 --- a/PHPCI/Builder.php +++ b/PHPCI/Builder.php @@ -28,6 +28,7 @@ class Builder $this->build->setStatus(1); $this->build->setStarted(new \DateTime()); $this->build = $this->store->save($this->build); + $this->build->sendStatusPostback(); if($this->setupBuild()) { @@ -60,6 +61,7 @@ class Builder $this->removeBuild(); + $this->build->sendStatusPostback(); $this->build->setFinished(new \DateTime()); $this->build->setLog($this->log); $this->build->setPlugins(json_encode($this->plugins)); diff --git a/PHPCI/Controller/GithubController.php b/PHPCI/Controller/GithubController.php index bd3c478d..7e1626b9 100644 --- a/PHPCI/Controller/GithubController.php +++ b/PHPCI/Controller/GithubController.php @@ -36,7 +36,8 @@ class GithubController extends b8\Controller try { - $this->_buildStore->save($build); + $build = $this->_buildStore->save($build); + $build->sendStatusPostback(); } catch(\Exception $ex) { diff --git a/PHPCI/Model/Base/ProjectBase.php b/PHPCI/Model/Base/ProjectBase.php index 451871e5..e7a2c915 100644 --- a/PHPCI/Model/Base/ProjectBase.php +++ b/PHPCI/Model/Base/ProjectBase.php @@ -21,6 +21,7 @@ class ProjectBase extends Model 'reference' => null, 'git_key' => null, 'type' => null, + 'token' => null, ); protected $_getters = array( 'id' => 'getId', @@ -28,6 +29,7 @@ class ProjectBase extends Model 'reference' => 'getReference', 'git_key' => 'getGitKey', 'type' => 'getType', + 'token' => 'getToken', ); @@ -38,6 +40,7 @@ class ProjectBase extends Model 'reference' => 'setReference', 'git_key' => 'setGitKey', 'type' => 'setType', + 'token' => 'setToken', ); public $columns = array( @@ -80,6 +83,14 @@ class ProjectBase extends Model + ), + 'token' => array( + 'type' => 'varchar', + 'length' => '50', + 'nullable' => true, + + + ), ); public $indexes = array( @@ -130,6 +141,14 @@ class ProjectBase extends Model return $rtn; } + public function getToken() + { + $rtn = $this->_data['token']; + + + return $rtn; + } + public function setId($value) @@ -202,6 +221,20 @@ class ProjectBase extends Model $this->_setModified('type'); } + public function setToken($value) + { + + $this->_validateString('Token', $value); + if($this->_data['token'] == $value) + { + return; + } + + $this->_data['token'] = $value; + + $this->_setModified('token'); + } + diff --git a/PHPCI/Model/Build.php b/PHPCI/Model/Build.php index 2ce4bb35..e57b8322 100644 --- a/PHPCI/Model/Build.php +++ b/PHPCI/Model/Build.php @@ -33,4 +33,38 @@ class Build extends BuildBase return 'https://github.com/' . $this->getProject()->getReference() . '/tree/' . $this->getBranch(); } } + + public function sendStatusPostback() + { + $project = $this->getProject(); + + if($project->getType() == 'github' && $project->getToken()) + { + $url = 'https://api.github.com/repos/'.$project->getReference().'/statuses/'.$this->build->getCommitId() . '?access_token=' . $project->getToken(); + $http = new \b8\HttpClient(); + + switch($this->getStatus()) + { + case 0: + case 1: + $status = 'pending'; + break; + + case 2: + $status = 'success'; + break; + + case 3: + $status = 'failure'; + break; + + default: + $status = 'error'; + break; + } + + $params = array('status' => $status, 'target_url' => \b8\Registry::getInstance()->get('install_url') . '/build/view/' . $this->getId()); + $http->post($url, $params); + } + } } diff --git a/PHPCI/View/ProjectForm.phtml b/PHPCI/View/ProjectForm.phtml index af1c7e43..4177215a 100644 --- a/PHPCI/View/ProjectForm.phtml +++ b/PHPCI/View/ProjectForm.phtml @@ -89,10 +89,7 @@ $(document).ready(function() $('#element-reference').hide(); $('#element-type').hide(); $('#element-token').val(window.github_token); - - if(!$('#element-title').val()) { - $('#element-title').val(val); - } + $('#element-title').val(val); } else { $('label[for=element-reference]').show(); diff --git a/install.php b/install.php index 96a611ae..52da6899 100644 --- a/install.php +++ b/install.php @@ -7,11 +7,14 @@ $dbHost = ask('Enter your MySQL host: '); $dbName = ask('Enter the database name PHPCI should use: '); $dbUser = ask('Enter your MySQL username: '); $dbPass = ask('Enter your MySQL password: ', true); +$ciUrl = ask('Your PHPCI URL (without trailing slash): ', true); +$ghId = ask('(Optional) Github Application ID: ', true); +$ghSecret = ask('(Optional) Github Application Secret: ', true); $cmd = 'mysql -u' . $dbUser . (!empty($dbPass) ? ' -p' . $dbPass : '') . ' -h' . $dbHost . ' -e "CREATE DATABASE IF NOT EXISTS ' . $dbName . '"'; shell_exec($cmd); -file_put_contents('./config.php', "set('install_url', '{$ciUrl}'); +"; + +if(!empty($ghId) && !empty($ghSecret)) +{ + $str .= PHP_EOL . "\$registry->set('github_app', array('id' => '{$ghId}', 'secret' => '{$ghSecret}'));" . PHP_EOL; +} + + +file_put_contents('./config.php', $str); if(!file_exists('./composer.phar')) { From 918b4deff4e630695dc8c5dc4929bee3362718b1 Mon Sep 17 00:00:00 2001 From: Dan Cryer Date: Tue, 14 May 2013 17:49:39 +0100 Subject: [PATCH 3/4] Adding Github statuses integration --- PHPCI/Controller/ProjectController.php | 3 +-- PHPCI/Controller/SessionController.php | 1 + PHPCI/Model/Build.php | 9 ++++++--- PHPCI/Plugin/Composer.php | 2 +- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/PHPCI/Controller/ProjectController.php b/PHPCI/Controller/ProjectController.php index f39c511c..00aeecb3 100644 --- a/PHPCI/Controller/ProjectController.php +++ b/PHPCI/Controller/ProjectController.php @@ -94,7 +94,7 @@ class ProjectController extends b8\Controller $pub = file_get_contents($id . '.pub'); $prv = file_get_contents($id); - $values = array('key' => $prv, 'pubkey' => $pub); + $values = array('key' => $prv, 'pubkey' => $pub, 'token' => $_SESSION['github_token']); } $form = $this->projectForm($values); @@ -201,7 +201,6 @@ class ProjectController extends b8\Controller if(isset($_SESSION['github_token'])) { $field = new Form\Element\Select('github'); - $field->setPattern('[a-zA-Z0-9_\-]+\/[a-zA-Z0-9_\-]+'); $field->setLabel('Choose a Github repository:'); $field->setClass('span4'); $field->setOptions($this->getGithubRepositories()); diff --git a/PHPCI/Controller/SessionController.php b/PHPCI/Controller/SessionController.php index 0551dd4e..bd1bfc1a 100644 --- a/PHPCI/Controller/SessionController.php +++ b/PHPCI/Controller/SessionController.php @@ -53,6 +53,7 @@ class SessionController extends b8\Controller public function logout() { unset($_SESSION['user_id']); + unset($_SESSION['github_token']); header('Location: /'); die; } diff --git a/PHPCI/Model/Build.php b/PHPCI/Model/Build.php index e57b8322..56b14010 100644 --- a/PHPCI/Model/Build.php +++ b/PHPCI/Model/Build.php @@ -40,7 +40,7 @@ class Build extends BuildBase if($project->getType() == 'github' && $project->getToken()) { - $url = 'https://api.github.com/repos/'.$project->getReference().'/statuses/'.$this->build->getCommitId() . '?access_token=' . $project->getToken(); + $url = 'https://api.github.com/repos/'.$project->getReference().'/statuses/'.$this->getCommitId(); $http = new \b8\HttpClient(); switch($this->getStatus()) @@ -63,8 +63,11 @@ class Build extends BuildBase break; } - $params = array('status' => $status, 'target_url' => \b8\Registry::getInstance()->get('install_url') . '/build/view/' . $this->getId()); - $http->post($url, $params); + $params = array( 'state' => $status, + 'target_url' => \b8\Registry::getInstance()->get('install_url') . '/build/view/' . $this->getId()); + + $http->setHeaders(array('Authorization: token ' . $project->getToken())); + $http->request('POST', $url, json_encode($params)); } } } diff --git a/PHPCI/Plugin/Composer.php b/PHPCI/Plugin/Composer.php index 0d470db4..ac73f7de 100644 --- a/PHPCI/Plugin/Composer.php +++ b/PHPCI/Plugin/Composer.php @@ -17,6 +17,6 @@ class Composer implements \PHPCI\Plugin public function execute() { - return $this->phpci->executeCommand(PHPCI_DIR . 'composer.phar --working-dir=' . $this->directory . ' ' . $this->action); + return $this->phpci->executeCommand(PHPCI_DIR . 'composer.phar --prefer-dist --working-dir=' . $this->directory . ' ' . $this->action); } } \ No newline at end of file From 5ae4ba03bf441856c35f54db47f846f4205c4507 Mon Sep 17 00:00:00 2001 From: Dan Cryer Date: Tue, 14 May 2013 20:00:52 +0100 Subject: [PATCH 4/4] Fixing phpci.yml, use spaces not tabs --- phpci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/phpci.yml b/phpci.yml index d252d83a..d70e867b 100644 --- a/phpci.yml +++ b/phpci.yml @@ -1,7 +1,7 @@ build_settings: - verbose: false - ignore: - - "vendor" + verbose: false + ignore: + - "vendor" setup: composer: