From ab1a4760ed5b35cf58fc6f3f4e3c31be4cff17f2 Mon Sep 17 00:00:00 2001 From: Frédéric Guillot Date: Mon, 22 Sep 2014 14:31:12 +0200 Subject: Basic prototype to handle Github webhooks --- app/Controller/Webhook.php | 61 ++++++++++++++++++++++++++++++++++ app/Core/Request.php | 2 +- app/Model/Acl.php | 3 +- app/Model/Action.php | 1 + app/Model/GithubWebhook.php | 81 +++++++++++++++++++++++++++++++++++++++++++++ app/Model/Task.php | 18 ++++++++++ app/functions.php | 4 +++ 7 files changed, 168 insertions(+), 2 deletions(-) create mode 100644 app/Controller/Webhook.php create mode 100644 app/Model/GithubWebhook.php (limited to 'app') diff --git a/app/Controller/Webhook.php b/app/Controller/Webhook.php new file mode 100644 index 00000000..8a81a0c4 --- /dev/null +++ b/app/Controller/Webhook.php @@ -0,0 +1,61 @@ +config->get('webhooks_token') !== $this->request->getStringParam('token')) { + $this->response->text('Not Authorized', 401); + } + + $defaultProject = $this->project->getFirst(); + + $values = array( + 'title' => $this->request->getStringParam('title'), + 'description' => $this->request->getStringParam('description'), + 'color_id' => $this->request->getStringParam('color_id'), + 'project_id' => $this->request->getIntegerParam('project_id', $defaultProject['id']), + 'owner_id' => $this->request->getIntegerParam('owner_id'), + 'column_id' => $this->request->getIntegerParam('column_id'), + 'category_id' => $this->request->getIntegerParam('category_id'), + ); + + list($valid,) = $this->taskValidator->validateCreation($values); + + if ($valid && $this->task->create($values)) { + $this->response->text('OK'); + } + + $this->response->text('FAILED'); + } + + /** + * Handle Github webhooks + * + * @access public + */ + public function github() + { + if ($this->config->get('webhooks_token') !== $this->request->getStringParam('token')) { + $this->response->text('Not Authorized', 401); + } + + $this->githubWebhook->parsePayload( + $this->request->getHeader('X-Github-Event'), + $this->request->getBody() + ); + } +} diff --git a/app/Core/Request.php b/app/Core/Request.php index e86cf609..09792013 100644 --- a/app/Core/Request.php +++ b/app/Core/Request.php @@ -145,7 +145,7 @@ class Request */ public function getQueryString() { - return $_SERVER['QUERY_STRING']; + return isset($_SERVER['QUERY_STRING']) ? $_SERVER['QUERY_STRING'] : ''; } } diff --git a/app/Model/Acl.php b/app/Model/Acl.php index aea13e8c..f92b3021 100644 --- a/app/Model/Acl.php +++ b/app/Model/Acl.php @@ -18,9 +18,10 @@ class Acl extends Base */ private $public_actions = array( 'user' => array('login', 'check', 'google', 'github'), - 'task' => array('add', 'readonly'), + 'task' => array('readonly'), 'board' => array('readonly'), 'project' => array('feed'), + 'webhook' => array('task', 'github'), ); /** diff --git a/app/Model/Action.php b/app/Model/Action.php index a318c5b0..a0c992aa 100644 --- a/app/Model/Action.php +++ b/app/Model/Action.php @@ -65,6 +65,7 @@ class Action extends Base Task::EVENT_CLOSE => t('Closing a task'), Task::EVENT_CREATE_UPDATE => t('Task creation or modification'), Task::EVENT_ASSIGNEE_CHANGE => t('Task assignee change'), + GithubWebhook::EVENT_COMMIT => t('Github commit received'), ); } diff --git a/app/Model/GithubWebhook.php b/app/Model/GithubWebhook.php new file mode 100644 index 00000000..688ab601 --- /dev/null +++ b/app/Model/GithubWebhook.php @@ -0,0 +1,81 @@ +parsePushEvent($payload); + case 'issues': + return $this->parseIssueEvent($payload); + } + } + + /** + * Parse Push events (list of commits) + * + * @access public + * @param array $payload Event data + */ + public function parsePushEvent(array $payload) + { + foreach ($payload['commits'] as $commit) { + + $task_id = $this->task->getTaskIdFromText($commit['message']); + + if (! $task_id) { + continue; + } + + $task = $this->task->getById($task_id); + + if (! $task) { + continue; + } + + if ($task['is_active'] == Task::STATUS_OPEN) { + $this->event->trigger(self::EVENT_COMMIT, array('task_id' => $task_id) + $task); + } + } + } + + /** + * Parse issue events + * + * @access public + * @param array $payload Event data + */ + public function parseIssueEvent(array $payload) + { + + } +} diff --git a/app/Model/Task.php b/app/Model/Task.php index 262e8d76..8708f128 100644 --- a/app/Model/Task.php +++ b/app/Model/Task.php @@ -696,4 +696,22 @@ class Task extends Base return false; } + + /** + * Get a the task id from a text + * + * Example: "Fix bug #1234" will return 1234 + * + * @access public + * @param string $message Text + * @return integer + */ + public function getTaskIdFromText($message) + { + if (preg_match('!#(\d+)!i', $message, $matches) && isset($matches[1])) { + return $matches[1]; + } + + return 0; + } } diff --git a/app/functions.php b/app/functions.php index 4cbbbbfe..dc6431b9 100644 --- a/app/functions.php +++ b/app/functions.php @@ -6,6 +6,10 @@ use PicoDb\Database; function debug($message) { + if (! is_string($message)) { + $message = var_export($message, true); + } + error_log($message.PHP_EOL, 3, 'data/debug.log'); } -- cgit v1.2.3