diff --git a/PHPCI/Builder.php b/PHPCI/Builder.php index f6e926d6..2d9607ff 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 { @@ -126,38 +127,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; } - $this->config = yaml_parse_file($this->buildPath . 'phpci.yml'); - - if(!isset($this->config['verbose']) || !$this->config['verbose']) + if(!isset($this->config['build_settings']['verbose']) || !$this->config['build_settings']['verbose']) { $this->verbose = false; } @@ -166,9 +210,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); @@ -184,6 +228,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 00aeecb3..d424f376 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() . '/'; + $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'); @@ -192,8 +196,8 @@ class ProjectController extends b8\Controller $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->setPattern('^(github|bitbucket|local)'); + $field->setOptions(array('choose' => 'Select repository type...', 'github' => 'Github', 'bitbucket' => 'Bitbucket', 'local' => 'Local Path')); $field->setLabel('Where is your project hosted?'); $field->setClass('span4'); $form->addField($field); @@ -209,8 +213,8 @@ class ProjectController extends b8\Controller $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->setPattern('[a-zA-Z0-9_\-\/]+'); + $field->setLabel('Repository Name / URL (Remote) or Path (Local)'); $field->setClass('span4'); $form->addField($field); @@ -222,7 +226,7 @@ class ProjectController extends b8\Controller $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/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 @@
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 @@