Add Bitbucket webhook
This commit is contained in:
parent
02f7c8d33d
commit
6f94ce6af3
|
|
@ -86,6 +86,7 @@ Documentation
|
|||
|
||||
### Integrations
|
||||
|
||||
- [Bitbucket webhooks](docs/bitbucket-webhooks.markdown)
|
||||
- [Github webhooks](docs/github-webhooks.markdown)
|
||||
- [Gitlab webhooks](docs/gitlab-webhooks.markdown)
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ namespace Action;
|
|||
|
||||
use Integration\GitlabWebhook;
|
||||
use Integration\GithubWebhook;
|
||||
use Integration\BitbucketWebhook;
|
||||
use Model\Task;
|
||||
|
||||
/**
|
||||
|
|
@ -28,6 +29,7 @@ class TaskClose extends Base
|
|||
GithubWebhook::EVENT_ISSUE_CLOSED,
|
||||
GitlabWebhook::EVENT_COMMIT,
|
||||
GitlabWebhook::EVENT_ISSUE_CLOSED,
|
||||
BitbucketWebhook::EVENT_COMMIT,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -44,6 +46,7 @@ class TaskClose extends Base
|
|||
case GithubWebhook::EVENT_ISSUE_CLOSED:
|
||||
case GitlabWebhook::EVENT_COMMIT:
|
||||
case GitlabWebhook::EVENT_ISSUE_CLOSED:
|
||||
case BitbucketWebhook::EVENT_COMMIT:
|
||||
return array();
|
||||
default:
|
||||
return array('column_id' => t('Column'));
|
||||
|
|
@ -63,6 +66,7 @@ class TaskClose extends Base
|
|||
case GithubWebhook::EVENT_ISSUE_CLOSED:
|
||||
case GitlabWebhook::EVENT_COMMIT:
|
||||
case GitlabWebhook::EVENT_ISSUE_CLOSED:
|
||||
case BitbucketWebhook::EVENT_COMMIT:
|
||||
return array('task_id');
|
||||
default:
|
||||
return array('task_id', 'column_id');
|
||||
|
|
@ -95,6 +99,7 @@ class TaskClose extends Base
|
|||
case GithubWebhook::EVENT_ISSUE_CLOSED:
|
||||
case GitlabWebhook::EVENT_COMMIT:
|
||||
case GitlabWebhook::EVENT_ISSUE_CLOSED:
|
||||
case BitbucketWebhook::EVENT_COMMIT:
|
||||
return true;
|
||||
default:
|
||||
return $data['column_id'] == $this->getParam('column_id');
|
||||
|
|
|
|||
|
|
@ -82,4 +82,22 @@ class Webhook extends Base
|
|||
|
||||
echo $result ? 'PARSED' : 'IGNORED';
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Bitbucket webhooks
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function bitbucket()
|
||||
{
|
||||
if ($this->config->get('webhook_token') !== $this->request->getStringParam('token')) {
|
||||
$this->response->text('Not Authorized', 401);
|
||||
}
|
||||
|
||||
$this->bitbucketWebhook->setProjectId($this->request->getIntegerParam('project_id'));
|
||||
|
||||
$result = $this->bitbucketWebhook->parsePayload(json_decode(@$_POST['payload'], true));
|
||||
|
||||
echo $result ? 'PARSED' : 'IGNORED';
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,98 @@
|
|||
<?php
|
||||
|
||||
namespace Integration;
|
||||
|
||||
use Event\GenericEvent;
|
||||
use Event\TaskEvent;
|
||||
use Model\Task;
|
||||
|
||||
/**
|
||||
* Bitbucket Webhook
|
||||
*
|
||||
* @package integration
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class BitbucketWebhook extends Base
|
||||
{
|
||||
/**
|
||||
* Events
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const EVENT_COMMIT = 'bitbucket.webhook.commit';
|
||||
|
||||
/**
|
||||
* Project id
|
||||
*
|
||||
* @access private
|
||||
* @var integer
|
||||
*/
|
||||
private $project_id = 0;
|
||||
|
||||
/**
|
||||
* Set the project id
|
||||
*
|
||||
* @access public
|
||||
* @param integer $project_id Project id
|
||||
*/
|
||||
public function setProjectId($project_id)
|
||||
{
|
||||
$this->project_id = $project_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse events
|
||||
*
|
||||
* @access public
|
||||
* @param array $payload Gitlab event
|
||||
* @return boolean
|
||||
*/
|
||||
public function parsePayload(array $payload)
|
||||
{
|
||||
if (! empty($payload['commits'])) {
|
||||
|
||||
foreach ($payload['commits'] as $commit) {
|
||||
|
||||
if ($this->handleCommit($commit)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse commit
|
||||
*
|
||||
* @access public
|
||||
* @param array $commit Gitlab commit
|
||||
* @return boolean
|
||||
*/
|
||||
public function handleCommit(array $commit)
|
||||
{
|
||||
$task_id = $this->task->getTaskIdFromText($commit['message']);
|
||||
|
||||
if (! $task_id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$task = $this->taskFinder->getById($task_id);
|
||||
|
||||
if (! $task) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($task['is_active'] == Task::STATUS_OPEN && $task['project_id'] == $this->project_id) {
|
||||
|
||||
$this->container['dispatcher']->dispatch(
|
||||
self::EVENT_COMMIT,
|
||||
new TaskEvent(array('task_id' => $task_id) + $task)
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -678,4 +678,7 @@ return array(
|
|||
// 'Disable login form' => '',
|
||||
// 'Show/hide calendar' => '',
|
||||
// 'User calendar' => '',
|
||||
// 'Bitbucket commit received' => '',
|
||||
// 'Bitbucket webhooks' => '',
|
||||
// 'Help on Bitbucket webhooks' => '',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -678,4 +678,7 @@ return array(
|
|||
// 'Disable login form' => '',
|
||||
// 'Show/hide calendar' => '',
|
||||
// 'User calendar' => '',
|
||||
// 'Bitbucket commit received' => '',
|
||||
// 'Bitbucket webhooks' => '',
|
||||
// 'Help on Bitbucket webhooks' => '',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -678,4 +678,7 @@ return array(
|
|||
// 'Disable login form' => '',
|
||||
// 'Show/hide calendar' => '',
|
||||
// 'User calendar' => '',
|
||||
// 'Bitbucket commit received' => '',
|
||||
// 'Bitbucket webhooks' => '',
|
||||
// 'Help on Bitbucket webhooks' => '',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -678,4 +678,7 @@ return array(
|
|||
// 'Disable login form' => '',
|
||||
// 'Show/hide calendar' => '',
|
||||
// 'User calendar' => '',
|
||||
// 'Bitbucket commit received' => '',
|
||||
// 'Bitbucket webhooks' => '',
|
||||
// 'Help on Bitbucket webhooks' => '',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -680,4 +680,7 @@ return array(
|
|||
'Disable login form' => 'Désactiver le formulaire d\'authentification',
|
||||
'Show/hide calendar' => 'Afficher/cacher le calendrier',
|
||||
'User calendar' => 'Calendrier de l\'utilisateur',
|
||||
'Bitbucket commit received' => '« Commit » reçu via Bitbucket',
|
||||
'Bitbucket webhooks' => 'Webhook Bitbucket',
|
||||
'Help on Bitbucket webhooks' => 'Aide sur les webhooks Bitbucket',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -678,4 +678,7 @@ return array(
|
|||
// 'Disable login form' => '',
|
||||
// 'Show/hide calendar' => '',
|
||||
// 'User calendar' => '',
|
||||
// 'Bitbucket commit received' => '',
|
||||
// 'Bitbucket webhooks' => '',
|
||||
// 'Help on Bitbucket webhooks' => '',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -678,4 +678,7 @@ return array(
|
|||
// 'Disable login form' => '',
|
||||
// 'Show/hide calendar' => '',
|
||||
// 'User calendar' => '',
|
||||
// 'Bitbucket commit received' => '',
|
||||
// 'Bitbucket webhooks' => '',
|
||||
// 'Help on Bitbucket webhooks' => '',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -678,4 +678,7 @@ return array(
|
|||
// 'Disable login form' => '',
|
||||
// 'Show/hide calendar' => '',
|
||||
// 'User calendar' => '',
|
||||
// 'Bitbucket commit received' => '',
|
||||
// 'Bitbucket webhooks' => '',
|
||||
// 'Help on Bitbucket webhooks' => '',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -678,4 +678,7 @@ return array(
|
|||
// 'Disable login form' => '',
|
||||
// 'Show/hide calendar' => '',
|
||||
// 'User calendar' => '',
|
||||
// 'Bitbucket commit received' => '',
|
||||
// 'Bitbucket webhooks' => '',
|
||||
// 'Help on Bitbucket webhooks' => '',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -678,4 +678,7 @@ return array(
|
|||
// 'Disable login form' => '',
|
||||
// 'Show/hide calendar' => '',
|
||||
// 'User calendar' => '',
|
||||
// 'Bitbucket commit received' => '',
|
||||
// 'Bitbucket webhooks' => '',
|
||||
// 'Help on Bitbucket webhooks' => '',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -678,4 +678,7 @@ return array(
|
|||
// 'Disable login form' => '',
|
||||
// 'Show/hide calendar' => '',
|
||||
// 'User calendar' => '',
|
||||
// 'Bitbucket commit received' => '',
|
||||
// 'Bitbucket webhooks' => '',
|
||||
// 'Help on Bitbucket webhooks' => '',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -678,4 +678,7 @@ return array(
|
|||
// 'Disable login form' => '',
|
||||
// 'Show/hide calendar' => '',
|
||||
// 'User calendar' => '',
|
||||
// 'Bitbucket commit received' => '',
|
||||
// 'Bitbucket webhooks' => '',
|
||||
// 'Help on Bitbucket webhooks' => '',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -678,4 +678,7 @@ return array(
|
|||
// 'Disable login form' => '',
|
||||
// 'Show/hide calendar' => '',
|
||||
// 'User calendar' => '',
|
||||
// 'Bitbucket commit received' => '',
|
||||
// 'Bitbucket webhooks' => '',
|
||||
// 'Help on Bitbucket webhooks' => '',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -678,4 +678,7 @@ return array(
|
|||
// 'Disable login form' => '',
|
||||
// 'Show/hide calendar' => '',
|
||||
// 'User calendar' => '',
|
||||
// 'Bitbucket commit received' => '',
|
||||
// 'Bitbucket webhooks' => '',
|
||||
// 'Help on Bitbucket webhooks' => '',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ namespace Model;
|
|||
|
||||
use Integration\GitlabWebhook;
|
||||
use Integration\GithubWebhook;
|
||||
use Integration\BitbucketWebhook;
|
||||
use SimpleValidator\Validator;
|
||||
use SimpleValidator\Validators;
|
||||
|
||||
|
|
@ -85,6 +86,7 @@ class Action extends Base
|
|||
GitlabWebhook::EVENT_COMMIT => t('Gitlab commit received'),
|
||||
GitlabWebhook::EVENT_ISSUE_OPENED => t('Gitlab issue opened'),
|
||||
GitlabWebhook::EVENT_ISSUE_CLOSED => t('Gitlab issue closed'),
|
||||
BitbucketWebhook::EVENT_COMMIT => t('Bitbucket commit received'),
|
||||
);
|
||||
|
||||
asort($values);
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ class ClassProvider implements ServiceProviderInterface
|
|||
'Integration' => array(
|
||||
'GitlabWebhook',
|
||||
'GithubWebhook',
|
||||
'BitbucketWebhook',
|
||||
)
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -12,4 +12,10 @@
|
|||
<div class="listing">
|
||||
<input type="text" class="auto-select" readonly="readonly" value="<?= $this->getCurrentBaseUrl().$this->u('webhook', 'gitlab', array('token' => $webhook_token, 'project_id' => $project['id'])) ?>"/><br/>
|
||||
<p class="form-help"><a href="http://kanboard.net/documentation/gitlab-webhooks" target="_blank"><?= t('Help on Gitlab webhooks') ?></a></p>
|
||||
</div>
|
||||
|
||||
<h3><i class="fa fa-bitbucket fa-fw"></i> <?= t('Bitbucket webhooks') ?></h3>
|
||||
<div class="listing">
|
||||
<input type="text" class="auto-select" readonly="readonly" value="<?= $this->getCurrentBaseUrl().$this->u('webhook', 'bitbucket', array('token' => $webhook_token, 'project_id' => $project['id'])) ?>"/><br/>
|
||||
<p class="form-help"><a href="http://kanboard.net/documentation/bitbucket-webhooks" target="_blank"><?= t('Help on Bitbucket webhooks') ?></a></p>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
Bitbucket webhooks
|
||||
==================
|
||||
|
||||
Bitbucket events can be connected to Kanboard automatic actions.
|
||||
|
||||
List of supported events
|
||||
------------------------
|
||||
|
||||
- Bitbucket commit received
|
||||
|
||||
List of supported actions
|
||||
-------------------------
|
||||
|
||||
- Close a task
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
||||

|
||||
|
||||
1. On Kanboard, go to the project settings and choose the section **Integrations**
|
||||
2. Copy the Bitbucket webhook url
|
||||
3. On Bitbucket, go to the project settings and go to the section **Hooks**
|
||||
4. Select the service **POST**
|
||||
5. Paste the url and save
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
### Close a Kanboard task when a commit pushed to Bitbucket
|
||||
|
||||
- Choose the event: **Bitbucket commit received**
|
||||
- Choose the action: **Close the task**
|
||||
|
||||
When one or more commits are sent to Bitbucket, Kanboard will receive the information, each commit message with a task number included will be closed.
|
||||
|
||||
Example:
|
||||
|
||||
- Commit message: "Fix bug #1234"
|
||||
- That will close the Kanboard task #1234
|
||||
|
|
@ -23,7 +23,7 @@ Configuration
|
|||
|
||||
1. On Kanboard, go to the project settings and choose the section **Integrations**
|
||||
2. Copy the Gitlab webhook url
|
||||
3. On Gitlab, go to the project settings and go the section **Webhooks**
|
||||
3. On Gitlab, go to the project settings and go to the section **Webhooks**
|
||||
4. Check the boxes **Push Events** and **Issues Events**
|
||||
5. Paste the url and save
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,65 @@
|
|||
<?php
|
||||
|
||||
require_once __DIR__.'/Base.php';
|
||||
|
||||
use Integration\BitbucketWebhook;
|
||||
use Model\TaskCreation;
|
||||
use Model\TaskFinder;
|
||||
use Model\Project;
|
||||
|
||||
class BitbucketWebhookTest extends Base
|
||||
{
|
||||
private $post_payload = '{"repository": {"website": "", "fork": false, "name": "webhooks", "scm": "git", "owner": "minicoders", "absolute_url": "/minicoders/webhooks/", "slug": "webhooks", "is_private": true}, "truncated": false, "commits": [{"node": "28569937627f", "files": [{"type": "added", "file": "README.md"}], "raw_author": "Frederic Guillot <fred@localhost>", "utctimestamp": "2015-02-09 00:57:45+00:00", "author": "Frederic Guillot", "timestamp": "2015-02-09 01:57:45", "raw_node": "28569937627fb406eeda9376a02b39581a974d4f", "parents": [], "branch": "master", "message": "first commit\\n", "revision": null, "size": -1}, {"node": "285699376274", "files": [{"type": "added", "file": "README.md"}], "raw_author": "Frederic Guillot <fred@localhost>", "utctimestamp": "2015-02-09 00:57:45+00:00", "author": "Frederic Guillot", "timestamp": "2015-02-09 01:57:45", "raw_node": "28569937627fb406eeda9376a02b39581a974d4f", "parents": [], "branch": "master", "message": "Fix #2\\n", "revision": null, "size": -1}], "canon_url": "https://bitbucket.org", "user": "minicoders"}';
|
||||
|
||||
public function testHandleCommit()
|
||||
{
|
||||
$g = new BitbucketWebhook($this->container);
|
||||
$p = new Project($this->container);
|
||||
$tc = new TaskCreation($this->container);
|
||||
$tf = new TaskFinder($this->container);
|
||||
|
||||
$this->assertEquals(1, $p->create(array('name' => 'test')));
|
||||
$g->setProjectId(1);
|
||||
|
||||
$this->container['dispatcher']->addListener(BitbucketWebhook::EVENT_COMMIT, function() {});
|
||||
|
||||
$event = json_decode($this->post_payload, true);
|
||||
|
||||
// No task
|
||||
$this->assertFalse($g->handleCommit($event['commits'][0]));
|
||||
|
||||
// Create task with the wrong id
|
||||
$this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1)));
|
||||
$this->assertFalse($g->handleCommit($event['commits'][1]));
|
||||
|
||||
// Create task with the right id
|
||||
$this->assertEquals(2, $tc->create(array('title' => 'test', 'project_id' => 1)));
|
||||
$this->assertTrue($g->handleCommit($event['commits'][1]));
|
||||
|
||||
$called = $this->container['dispatcher']->getCalledListeners();
|
||||
$this->assertArrayHasKey(BitbucketWebhook::EVENT_COMMIT.'.closure', $called);
|
||||
}
|
||||
|
||||
public function testParsePayload()
|
||||
{
|
||||
$g = new BitbucketWebhook($this->container);
|
||||
$p = new Project($this->container);
|
||||
$tc = new TaskCreation($this->container);
|
||||
$tf = new TaskFinder($this->container);
|
||||
|
||||
$this->container['dispatcher']->addListener(BitbucketWebhook::EVENT_COMMIT, function() {});
|
||||
|
||||
$this->assertEquals(1, $p->create(array('name' => 'test')));
|
||||
|
||||
$g->setProjectId(1);
|
||||
|
||||
$this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1)));
|
||||
$this->assertEquals(2, $tc->create(array('title' => 'test', 'project_id' => 1)));
|
||||
|
||||
$event = json_decode($this->post_payload, true);
|
||||
$this->assertTrue($g->parsePayload($event));
|
||||
|
||||
$called = $this->container['dispatcher']->getCalledListeners();
|
||||
$this->assertArrayHasKey(BitbucketWebhook::EVENT_COMMIT.'.closure', $called);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue