From 0c13e984e3c528ee9a8d3636ee96636a48087abe Mon Sep 17 00:00:00 2001 From: Dan Cryer Date: Mon, 12 May 2014 15:53:29 +0100 Subject: [PATCH] Cleaning up the WebhookController class, making it actually send status postbacks, skipping duplicate commits --- PHPCI/Controller/WebhookController.php | 130 ++++++++++--------------- PHPCI/Store/BuildStore.php | 22 +++++ 2 files changed, 75 insertions(+), 77 deletions(-) diff --git a/PHPCI/Controller/WebhookController.php b/PHPCI/Controller/WebhookController.php index cfd4de9c..4044e953 100644 --- a/PHPCI/Controller/WebhookController.php +++ b/PHPCI/Controller/WebhookController.php @@ -11,6 +11,7 @@ namespace PHPCI\Controller; use b8; use b8\Store; +use PHPCI\BuildFactory; use PHPCI\Model\Build; /** @@ -42,21 +43,16 @@ class WebhookController extends \PHPCI\Controller foreach ($payload['commits'] as $commit) { try { + $email = $commit['raw_author']; $email = substr($email, 0, strpos($email, '>')); $email = substr($email, strpos($email, '<') + 1); - $build = new Build(); - $build->setProjectId($project); - $build->setCommitId($commit['raw_node']); - $build->setCommitterEmail($email); - $build->setStatus(Build::STATUS_NEW); - $build->setLog(''); - $build->setCreated(new \DateTime()); - $build->setBranch($commit['branch']); - $build->setCommitMessage($commit['message']); - $this->buildStore->save($build); + $this->createBuild($project, $commit['raw_node'], $commit['branch'], $email, $commit['message']); } catch (\Exception $ex) { + header('HTTP/1.1 500 Internal Server Error'); + header('Ex: ' . $ex->getMessage()); + die('FAIL'); } } @@ -74,36 +70,22 @@ class WebhookController extends \PHPCI\Controller $commit = $this->getParam('commit'); try { - $build = new Build(); - $build->setProjectId($project); - - if ($branch !== null && trim($branch) !== '') { - $build->setBranch($branch); - } else { - $build->setBranch('master'); + if (empty($branch)) { + $branch = 'master'; } - if ($commit !== null && trim($commit) !== '') { - $build->setCommitId($commit); + if (empty($commit)) { + $commit = null; } - $build->setStatus(Build::STATUS_NEW); - $build->setLog(''); - $build->setCreated(new \DateTime()); + $this->createBuild($project, $commit, $branch, null, null); + } catch (\Exception $ex) { header('HTTP/1.1 400 Bad Request'); header('Ex: ' . $ex->getMessage()); die('FAIL'); } - try { - $this->buildStore->save($build); /** bugfix: Errors with PHPCI GitHub hook #296 */ - } catch (\Exception $ex) { - header('HTTP/1.1 500 Internal Server Error'); - header('Ex: ' . $ex->getMessage()); - die('FAIL'); - } - die('OK'); } @@ -146,32 +128,16 @@ class WebhookController extends \PHPCI\Controller continue; } - $build = new Build(); - $build->setProjectId($project); - $build->setCommitId($commit['id']); - $build->setStatus(Build::STATUS_NEW); - $build->setLog(''); - $build->setCreated(new \DateTime()); - $build->setBranch(str_replace('refs/heads/', '', $payload['ref'])); - $build->setCommitterEmail($commit['committer']['email']); - $build->setCommitMessage($commit['message']); - $build = $this->buildStore->save($build); - $build->sendStatusPostback(); + $branch = str_replace('refs/heads/', '', $payload['ref']); + $committer = $commit['committer']['email']; + $this->createBuild($project, $commit['id'], $branch, $committer, $commit['message']); } } elseif (substr($payload['ref'], 0, 10) == 'refs/tags/') { // If we don't, but we're dealing with a tag, add that instead: - $build = new Build(); - $build->setProjectId($project); - $build->setCommitId($payload['after']); - $build->setStatus(Build::STATUS_NEW); - $build->setLog(''); - $build->setCreated(new \DateTime()); - $build->setBranch(str_replace('refs/tags/', 'Tag: ', $payload['ref'])); - $build->setCommitterEmail($payload['pusher']['email']); - $build->setCommitMessage($payload['head_commit']['message']); - - $build = $this->buildStore->save($build); - $build->sendStatusPostback(); + $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) { @@ -211,15 +177,9 @@ class WebhookController extends \PHPCI\Controller } foreach ($response['body'] as $commit) { - $build = new Build(); - $build->setProjectId($projectId); - $build->setCommitId($commit['sha']); - $build->setStatus(Build::STATUS_NEW); - $build->setLog(''); - $build->setCreated(new \DateTime()); - $build->setBranch(str_replace('refs/heads/', '', $payload['pull_request']['base']['ref'])); - $build->setCommitterEmail($commit['commit']['author']['email']); - $build->setCommitMessage($commit['commit']['message']); + $branch = str_replace('refs/heads/', '', $payload['pull_request']['base']['ref']); + $committer = $commit['commit']['author']['email']; + $message = $commit['commit']['message']; $extra = array( 'build_type' => 'pull_request', @@ -229,10 +189,7 @@ class WebhookController extends \PHPCI\Controller 'remote_url' => $payload['pull_request']['head']['repo']['clone_url'], ); - $build->setExtra(json_encode($extra)); - - $build = $this->buildStore->save($build); - $build->sendStatusPostback(); + $this->createBuild($projectId, $commit['sha'], $branch, $committer, $message, $extra); } } catch (\Exception $ex) { header('HTTP/1.1 500 Internal Server Error'); @@ -257,17 +214,9 @@ class WebhookController extends \PHPCI\Controller // If we have a list of commits, then add them all as builds to be tested: foreach ($payload['commits'] as $commit) { - $build = new Build(); - $build->setProjectId($project); - $build->setCommitId($commit['id']); - $build->setStatus(Build::STATUS_NEW); - $build->setLog(''); - $build->setCreated(new \DateTime()); - $build->setBranch(str_replace('refs/heads/', '', $payload['ref'])); - $build->setCommitterEmail($commit['author']['email']); - $build->setCommitMessage($commit['message']); - $build = $this->buildStore->save($build); - $build->sendStatusPostback(); + $branch = str_replace('refs/heads/', '', $payload['ref']); + $committer = $commit['author']['email']; + $this->createBuild($project, $commit['id'], $branch, $committer, $commit['message']); } } @@ -279,4 +228,31 @@ class WebhookController extends \PHPCI\Controller die('OK'); } + + protected function createBuild($projectId, $commitId, $branch, $committer, $commitMessage, $extra = array()) + { + // Check if a build already exists for this commit ID: + $builds = $this->buildStore->getByProjectAndCommit($projectId, $commitId); + + if ($builds['count']) { + return true; + } + + // If not, create a new build job for it: + $build = new Build(); + $build->setProjectId($projectId); + $build->setCommitId($commitId); + $build->setStatus(Build::STATUS_NEW); + $build->setLog(''); + $build->setCreated(new \DateTime()); + $build->setBranch($branch); + $build->setCommitterEmail($committer); + $build->setCommitMessage($commitMessage); + $build = BuildFactory::getBuild($this->buildStore->save($build)); + + // Send a status postback if the build type provides one: + $build->sendStatusPostback(); + + return true; + } } diff --git a/PHPCI/Store/BuildStore.php b/PHPCI/Store/BuildStore.php index e419c9cc..41d0a6f0 100644 --- a/PHPCI/Store/BuildStore.php +++ b/PHPCI/Store/BuildStore.php @@ -39,6 +39,28 @@ class BuildStore extends BuildStoreBase } } + public function getByProjectAndCommit($projectId, $commitId) + { + $query = 'SELECT * FROM `build` WHERE `project_id` = :project_id AND `commit_id` = :commit_id'; + $stmt = Database::getConnection('read')->prepare($query); + $stmt->bindValue(':project_id', $projectId); + $stmt->bindValue(':commit_id', $commitId); + + if ($stmt->execute()) { + $res = $stmt->fetchAll(\PDO::FETCH_ASSOC); + + $map = function ($item) { + return new Build($item); + }; + + $rtn = array_map($map, $res); + + return array('items' => $rtn, 'count' => count($rtn)); + } else { + return array('items' => array(), 'count' => 0); + } + } + public function getMeta($key, $projectId, $buildId = null, $numResults = 1) { $select = '`build_id`, `meta_key`, `meta_value`';