From 0a9c7bda93206013387f41be5bb4f4b7447e7f86 Mon Sep 17 00:00:00 2001 From: meadsteve Date: Tue, 14 May 2013 18:01:14 +0100 Subject: [PATCH 1/6] On a windows system having a file path like '/tmp/' . md5(microtime(true)) caused problems. I've updated this to use the system temp directory. --- PHPCI/Controller/ProjectController.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/PHPCI/Controller/ProjectController.php b/PHPCI/Controller/ProjectController.php index d0834df8..ebbf1375 100644 --- a/PHPCI/Controller/ProjectController.php +++ b/PHPCI/Controller/ProjectController.php @@ -88,7 +88,11 @@ class ProjectController extends b8\Controller } else { - $id = '/tmp/' . md5(microtime(true)); + $tempPath = sys_get_temp_dir() . '/tmp/'; + $id = $tempPath . md5(microtime(true)); + if (!is_dir($tempPath)) { + mkdir($tempPath); + } shell_exec('ssh-keygen -q -t rsa -b 2048 -f '.$id.' -N "" -C "deploy@phpci"'); $pub = file_get_contents($id . '.pub'); From bdaf5abff7346382f1d0f5c9fb45aa5316476fae Mon Sep 17 00:00:00 2001 From: meadsteve Date: Tue, 14 May 2013 18:07:46 +0100 Subject: [PATCH 2/6] I've replaced the requirement for the pecl yaml extension with the symphony component. Sometimes I work on a windows box and the instructions for installing pecl yaml on windows looked a little intimidating: https://code.google.com/p/php-yaml/wiki/InstallingWithPecl --- PHPCI/Builder.php | 5 ++++- composer.json | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/PHPCI/Builder.php b/PHPCI/Builder.php index 7c3c1dc1..1f9d29b1 100644 --- a/PHPCI/Builder.php +++ b/PHPCI/Builder.php @@ -3,6 +3,7 @@ namespace PHPCI; use PHPCI\Model\Build; use b8\Store; +use Symfony\Component\Yaml\Parser as YamlParser; class Builder { @@ -153,7 +154,9 @@ class Builder return false; } - $this->config = yaml_parse_file($this->buildPath . 'phpci.yml'); + $yamlParser = new YamlParser(); + $yamlFile = file_get_contents($this->buildPath . 'phpci.yml'); + $this->config = $yamlParser->parse($yamlFile); if(!isset($this->config['verbose']) || !$this->config['verbose']) { diff --git a/composer.json b/composer.json index 22367854..78e5eefe 100644 --- a/composer.json +++ b/composer.json @@ -30,6 +30,6 @@ "squizlabs/php_codesniffer": "1.*", "ircmaxell/password-compat": "1.x", "phpspec/phpspec": "2.*", - "ext-yaml": "*" + "symfony/yaml": "2.2.x-dev" } -} \ No newline at end of file +} From b71849a9c437e5d9b97a4c38c035fe38393fe5b8 Mon Sep 17 00:00:00 2001 From: meadsteve Date: Tue, 14 May 2013 18:07:46 +0100 Subject: [PATCH 3/6] I've replaced the requirement for the pecl yaml extension with the symphony component. Sometimes I work on a windows box and the instructions for installing pecl yaml on windows looked a little intimidating: https://code.google.com/p/php-yaml/wiki/InstallingWithPecl --- PHPCI/Builder.php | 5 ++++- composer.json | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/PHPCI/Builder.php b/PHPCI/Builder.php index 7c3c1dc1..1f9d29b1 100644 --- a/PHPCI/Builder.php +++ b/PHPCI/Builder.php @@ -3,6 +3,7 @@ namespace PHPCI; use PHPCI\Model\Build; use b8\Store; +use Symfony\Component\Yaml\Parser as YamlParser; class Builder { @@ -153,7 +154,9 @@ class Builder return false; } - $this->config = yaml_parse_file($this->buildPath . 'phpci.yml'); + $yamlParser = new YamlParser(); + $yamlFile = file_get_contents($this->buildPath . 'phpci.yml'); + $this->config = $yamlParser->parse($yamlFile); if(!isset($this->config['verbose']) || !$this->config['verbose']) { diff --git a/composer.json b/composer.json index 22367854..78e5eefe 100644 --- a/composer.json +++ b/composer.json @@ -30,6 +30,6 @@ "squizlabs/php_codesniffer": "1.*", "ircmaxell/password-compat": "1.x", "phpspec/phpspec": "2.*", - "ext-yaml": "*" + "symfony/yaml": "2.2.x-dev" } -} \ No newline at end of file +} From fa7ad2f45ddea003258b0448fd1038650ec2f66b Mon Sep 17 00:00:00 2001 From: Dan Cryer Date: Tue, 14 May 2013 18:28:03 +0100 Subject: [PATCH 4/6] Removing short open tags and replacing with print statements. --- PHPCI/View/Build.phtml | 16 ++++++++-------- PHPCI/View/BuildsTable.phtml | 16 ++++++++-------- PHPCI/View/Index.phtml | 4 ++-- PHPCI/View/Layout.phtml | 2 +- PHPCI/View/Login.phtml | 3 +-- PHPCI/View/Project.phtml | 14 +++++++------- PHPCI/View/ProjectForm.phtml | 6 +++--- PHPCI/View/User.phtml | 12 ++++++------ PHPCI/View/UserForm.phtml | 4 ++-- 9 files changed, 38 insertions(+), 39 deletions(-) diff --git a/PHPCI/View/Build.phtml b/PHPCI/View/Build.phtml index 0ff07932..b34722a0 100644 --- a/PHPCI/View/Build.phtml +++ b/PHPCI/View/Build.phtml @@ -1,6 +1,6 @@
-

Build #getId(); ?>

-

Branch: getBranch(); ?> - getCommitId() == 'Manual' ? 'Manual Build' : 'Commit: ' . $build->getCommitId(); ?>

+

Build #getId(); ?>

+

Branch: getBranch(); ?> - getCommitId() == 'Manual' ? 'Manual Build' : 'Commit: ' . $build->getCommitId(); ?>

@@ -8,12 +8,12 @@ @@ -25,7 +25,7 @@ - +
@@ -68,13 +68,13 @@ \ No newline at end of file diff --git a/PHPCI/View/ProjectForm.phtml b/PHPCI/View/ProjectForm.phtml index d941af80..d0da4061 100644 --- a/PHPCI/View/ProjectForm.phtml +++ b/PHPCI/View/ProjectForm.phtml @@ -1,5 +1,5 @@
-

+

@@ -8,7 +8,7 @@

To make it easier to get started, we've generated a public / private key pair for you to use for this project. To use it, just add the following public key to the "deploy keys" section of your repository settings on Github / Bitbucket.

- +

Fill in the form to the right to add your new project.

@@ -17,7 +17,7 @@
- +
diff --git a/PHPCI/View/User.phtml b/PHPCI/View/User.phtml index 32700af4..d9a67095 100644 --- a/PHPCI/View/User.phtml +++ b/PHPCI/View/User.phtml @@ -40,19 +40,19 @@ break; } ?> - - getEmail(); ?> - getName(); ?> - + + getEmail(); ?> + getName(); ?> + User()->getIsAdmin()): ?> diff --git a/PHPCI/View/UserForm.phtml b/PHPCI/View/UserForm.phtml index 9a11ba82..c99a3cfd 100644 --- a/PHPCI/View/UserForm.phtml +++ b/PHPCI/View/UserForm.phtml @@ -1,5 +1,5 @@
-

getName() ?>

+

getName() ?>

@@ -13,6 +13,6 @@
- +
\ No newline at end of file From 5f9f839613efd5112188c679cce07574127ffdde Mon Sep 17 00:00:00 2001 From: Dan Cryer Date: Tue, 14 May 2013 18:34:26 +0100 Subject: [PATCH 5/6] Removing the extra /tmp from sys_get_temp_dir() --- PHPCI/Controller/ProjectController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PHPCI/Controller/ProjectController.php b/PHPCI/Controller/ProjectController.php index ebbf1375..e13ee5d1 100644 --- a/PHPCI/Controller/ProjectController.php +++ b/PHPCI/Controller/ProjectController.php @@ -88,7 +88,7 @@ class ProjectController extends b8\Controller } else { - $tempPath = sys_get_temp_dir() . '/tmp/'; + $tempPath = sys_get_temp_dir() . '/'; $id = $tempPath . md5(microtime(true)); if (!is_dir($tempPath)) { mkdir($tempPath); From fa18d89ddc0db7d0bb466055ef647586d6f8e3f6 Mon Sep 17 00:00:00 2001 From: Dan Cryer Date: Tue, 14 May 2013 19:44:14 +0100 Subject: [PATCH 6/6] Adding support for local path based projects. See pull #2 --- PHPCI/Builder.php | 103 ++++++++++++++++++------- PHPCI/Controller/ProjectController.php | 8 +- PHPCI/Plugin/PhpSpec.php | 12 +-- PHPCI/Plugin/PhpUnit.php | 7 +- README.md | 14 ++-- phpci.yml | 8 +- 6 files changed, 104 insertions(+), 48 deletions(-) diff --git a/PHPCI/Builder.php b/PHPCI/Builder.php index 1f9d29b1..2f1b870e 100644 --- a/PHPCI/Builder.php +++ b/PHPCI/Builder.php @@ -125,40 +125,81 @@ class Builder $commitId = $this->build->getCommitId(); $url = $this->build->getProject()->getGitUrl(); $key = $this->build->getProject()->getGitKey(); - + $type = $this->build->getProject()->getType(); + $reference = $this->build->getProject()->getReference(); + $reference = substr($reference, -1) == '/' ? substr($reference, 0, -1) : $reference; $buildId = 'project' . $this->build->getProject()->getId() . '-build' . $this->build->getId(); + $yamlParser = new YamlParser(); $this->ciDir = realpath(dirname(__FILE__) . '/../') . '/'; $this->buildPath = $this->ciDir . 'build/' . $buildId . '/'; - mkdir($this->buildPath, 0777, true); + switch ($type) + { + case 'local': + $this->buildPath = $this->ciDir . 'build/' . $buildId; + + if(!is_file($reference . '/phpci.yml')) + { + $this->logFailure('Project does not contain a phpci.yml file.'); + return false; + } - if(!empty($key)) - { - // Do an SSH clone: - $keyFile = $this->ciDir . 'build/' . $buildId . '.key'; - file_put_contents($keyFile, $key); - chmod($keyFile, 0600); - $this->executeCommand('ssh-agent ssh-add '.$keyFile.' && git clone -b ' .$this->build->getBranch() . ' ' .$url.' '.$this->buildPath.' && ssh-agent -k'); - unlink($keyFile); - } - else - { - // Do an HTTP clone: - $this->executeCommand('git clone -b ' .$this->build->getBranch() . ' ' .$url.' '.$this->buildPath); - } - - if(!is_file($this->buildPath . 'phpci.yml')) - { - $this->logFailure('Project does not contain a phpci.yml file.'); - return false; + $yamlFile = file_get_contents($reference . '/phpci.yml'); + $this->config = $yamlParser->parse($yamlFile); + + if(array_key_exists('build_settings', $this->config) + && is_array($this->config['build_settings']) + && array_key_exists('prefer_symlink', $this->config['build_settings']) + && true === $this->config['build_settings']['prefer_symlink']) + { + if(is_link($this->buildPath) && is_file($this->buildPath)) + { + unlink($this->buildPath); + } + + $this->log(sprintf('Symlinking: %s to %s',$reference, $this->buildPath)); + symlink($reference, $this->buildPath); + } + else + { + $this->executeCommand(sprintf("cp -Rf %s %s/", $reference, $this->buildPath)); + } + + $this->buildPath .= '/'; + break; + + case 'github': + case 'bitbucket': + mkdir($this->buildPath, 0777, true); + + if(!empty($key)) + { + // Do an SSH clone: + $keyFile = $this->ciDir . 'build/' . $buildId . '.key'; + file_put_contents($keyFile, $key); + chmod($keyFile, 0600); + $this->executeCommand('ssh-agent ssh-add '.$keyFile.' && git clone -b ' .$this->build->getBranch() . ' ' .$url.' '.$this->buildPath.' && ssh-agent -k'); + unlink($keyFile); + } + else + { + // Do an HTTP clone: + $this->executeCommand('git clone -b ' .$this->build->getBranch() . ' ' .$url.' '.$this->buildPath); + } + + if(!is_file($this->buildPath . 'phpci.yml')) + { + $this->logFailure('Project does not contain a phpci.yml file.'); + return false; + } + + $yamlFile = file_get_contents($this->buildPath . 'phpci.yml'); + $this->config = $yamlParser->parse($yamlFile); + break; } - $yamlParser = new YamlParser(); - $yamlFile = file_get_contents($this->buildPath . 'phpci.yml'); - $this->config = $yamlParser->parse($yamlFile); - - if(!isset($this->config['verbose']) || !$this->config['verbose']) + if(!isset($this->config['build_settings']['verbose']) || !$this->config['build_settings']['verbose']) { $this->verbose = false; } @@ -167,9 +208,9 @@ class Builder $this->verbose = true; } - if(isset($this->config['ignore'])) + if(isset($this->config['build_settings']['ignore'])) { - $this->ignore = $this->config['ignore']; + $this->ignore = $this->config['build_settings']['ignore']; } $this->log('Set up build: ' . $this->buildPath); @@ -185,6 +226,12 @@ class Builder protected function executePlugins($stage) { + // Ignore any stages for which we don't have plugins set: + if(!array_key_exists($stage, $this->config) || !is_array($this->config[$stage])) + { + return; + } + foreach($this->config[$stage] as $plugin => $options) { $this->log(''); diff --git a/PHPCI/Controller/ProjectController.php b/PHPCI/Controller/ProjectController.php index e13ee5d1..fecb424b 100644 --- a/PHPCI/Controller/ProjectController.php +++ b/PHPCI/Controller/ProjectController.php @@ -184,21 +184,21 @@ class ProjectController extends b8\Controller $field = new Form\Element\Select('type'); $field->setRequired(true); - $field->setOptions(array('github' => 'Github', 'bitbucket' => 'Bitbucket')); + $field->setOptions(array('github' => 'Github', 'bitbucket' => 'Bitbucket', 'local' => 'Local Path')); $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->setPattern('[a-zA-Z0-9_\-\/]+'); + $field->setLabel('Repository Name / URL (Remote) or Path (Local)'); $field->setClass('span4'); $form->addField($field); $field = new Form\Element\TextArea('key'); $field->setRequired(false); - $field->setLabel('Private key to use to access repository (leave blank to use anonymous HTTP repository access)'); + $field->setLabel('Private key to use to access repository (leave blank for local and/or anonymous remotes)'); $field->setClass('span7'); $field->setRows(6); $form->addField($field); diff --git a/PHPCI/Plugin/PhpSpec.php b/PHPCI/Plugin/PhpSpec.php index 75030161..2bcab4a6 100644 --- a/PHPCI/Plugin/PhpSpec.php +++ b/PHPCI/Plugin/PhpSpec.php @@ -13,11 +13,11 @@ class PhpSpec implements \PHPCI\Plugin public function execute() { - $cwd = getcwd(); - - $command = 'cd ' . $this->phpci->buildPath . ' && '; - $command .= PHPCI_BIN_DIR . 'phpspec'; - $command .= ' && cd ' . $cwd; - return $this->phpci->executeCommand($command); + $curdir = getcwd(); + chdir($this->phpci->buildPath); + $success = $this->phpci->executeCommand(PHPCI_BIN_DIR . 'phpspec'); + chdir($curdir); + + return $success; } } \ No newline at end of file diff --git a/PHPCI/Plugin/PhpUnit.php b/PHPCI/Plugin/PhpUnit.php index d34ee3d5..34817f11 100644 --- a/PHPCI/Plugin/PhpUnit.php +++ b/PHPCI/Plugin/PhpUnit.php @@ -17,6 +17,11 @@ class PhpUnit implements \PHPCI\Plugin public function execute() { - return $this->phpci->executeCommand(PHPCI_BIN_DIR . 'phpunit ' . $this->args . ' ' . $this->phpci->buildPath . $this->directory); + $curdir = getcwd(); + chdir($this->phpci->buildPath); + $success = $this->phpci->executeCommand(PHPCI_BIN_DIR . 'phpunit ' . $this->args . ' ' . $this->phpci->buildPath . $this->directory); + chdir($curdir); + + return $success; } } \ No newline at end of file diff --git a/README.md b/README.md index 082b93a4..7006ef2a 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ PHPCI is a free and open source continuous integration tool specifically designe _**Please be aware that this is a brand new project, in an alpha state, so there will be bugs and missing features.**_ ##What it does: -* Clones your repository from Github or Bitbucket (support for standard Git repositories coming soon.) +* Clones your project from Github, Bitbucket or a local path (support for standard remote Git repositories coming soon.) * Allows you to set up and tear down test databases. * Installs your project's Composer dependencies. * Runs through any combination of the following plugins: @@ -14,6 +14,7 @@ _**Please be aware that this is a brand new project, in an alpha state, so there * PHP Mess Detector * PHP Copy/Paste Detector * PHP Code Sniffer + * PHP Spec * You can mark directories for the plugins to ignore. * You can mark certain plugins as being allowed to fail (but still run.) @@ -67,7 +68,12 @@ Obviously, make sure you change the `/path/to/phpci` to the directory in which y ##Adding support for PHPCI to your projects: Similar to Travis CI, to support PHPCI in your project, you simply need to add a `phpci.yml` file to the root of your repository. The file should look something like this: - setup: + build_settings: + ignore: + - "vendor" + - "tests" + + setup: mysql: - "DROP DATABASE IF EXISTS test;" - "CREATE DATABASE test;" @@ -75,10 +81,6 @@ Similar to Travis CI, to support PHPCI in your project, you simply need to add a composer: action: "install" - ignore: - - "vendor" - - "tests" - test: php_unit: directory: "tests/" diff --git a/phpci.yml b/phpci.yml index 87c592b3..d252d83a 100644 --- a/phpci.yml +++ b/phpci.yml @@ -1,10 +1,12 @@ +build_settings: + verbose: false + ignore: + - "vendor" + setup: composer: action: "install" -ignore: - - "vendor/" - test: php_mess_detector: allow_failures: true \ No newline at end of file