webhooks: Add Bitbucket Server integration.

This commit adds support for all "repo" events.
This commit is contained in:
Hemanth V. Alluri
2019-03-03 22:14:33 +05:30
committed by Eeshan Garg
parent 33b064aa29
commit 9ed1dcc4b6
19 changed files with 1254 additions and 2 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View File

@@ -264,6 +264,13 @@ WEBHOOK_INTEGRATIONS = [
WebhookIntegration('beanstalk', ['version-control'], stream_name='commits'),
WebhookIntegration('basecamp', ['project-management']),
WebhookIntegration('beeminder', ['misc'], display_name='Beeminder'),
WebhookIntegration(
'bitbucket3',
['version-control'],
logo='static/images/integrations/logos/bitbucket.svg',
display_name='Bitbucket Server',
stream_name='bitbucket'
),
WebhookIntegration(
'bitbucket2',
['version-control'],

View File

@@ -31,6 +31,7 @@ PUSH_COMMITTERS_LIMIT_INFO = 3
FORCE_PUSH_COMMITS_MESSAGE_TEMPLATE = ("{user_name} [force pushed]({url}) "
"to branch {branch_name}. Head is now {head}")
CREATE_BRANCH_MESSAGE_TEMPLATE = "{user_name} created [{branch_name}]({url}) branch"
CREATE_BRANCH_WITHOUT_URL_MESSAGE_TEMPLATE = "{user_name} created {branch_name} branch"
REMOVE_BRANCH_MESSAGE_TEMPLATE = "{user_name} deleted branch {branch_name}"
PULL_REQUEST_OR_ISSUE_MESSAGE_TEMPLATE = "{user_name} {action} [{type}{id}]({url})"
@@ -108,7 +109,12 @@ def get_force_push_commits_event_message(user_name: str, url: str, branch_name:
head=head
)
def get_create_branch_event_message(user_name: str, url: str, branch_name: str) -> str:
def get_create_branch_event_message(user_name: str, url: Optional[str], branch_name: str) -> str:
if url is None:
return CREATE_BRANCH_WITHOUT_URL_MESSAGE_TEMPLATE.format(
user_name=user_name,
branch_name=branch_name,
)
return CREATE_BRANCH_MESSAGE_TEMPLATE.format(
user_name=user_name,
url=url,

View File

@@ -3,7 +3,8 @@ Bitbucket. This integration is for the new-style Bitbucket
webhooks used by the Bitbucket SAAS service.
For the old-style Bitbucket webhooks used by Bitbucket Enterprise,
click [here](./bitbucket).
click [here](./bitbucket), and for the new-style webhooks used by
Bitbucket Server click [here](./bitbucket3).
1. {!create-stream.md!}

View File

View File

@@ -0,0 +1,23 @@
Zulip supports both Git and Mercurial notifications from
Bitbucket. This integration is for the the new-style Bitbucket
webhooks used by Bitbucket Server.
For the old-style Bitbucket webhooks used by Bitbucket Enterprise,
click [here](./bitbucket), and for the new-style webhooks used by
Bitbucket Cloud (SAAS service) click [here](./bitbucket2).
1. {!create-stream.md!}
2. {!create-bot-construct-url-indented.md!}
{!git-webhook-url-with-branches-indented.md!}
3. On your repository's web page, click on **Settings**. Select
**Webhooks**, and click **Add webhook**.
4. Set **Title** to a title of your choice, such as `Zuilp`. Set **URL**
to the URL constructed above, and check the **Active** checkbox. Select
the **Triggers** you'd like to be notified about, and click **Save**.
{!congrats.md!}
![](/static/images/integrations/bitbucket/004.png)

View File

@@ -0,0 +1,90 @@
{
"actor": {
"active": true,
"type": "NORMAL",
"links": {
"self": [
{
"href": "http://139.59.64.214:7990/users/hypro999"
}
]
},
"displayName": "Hemanth V. Alluri",
"emailAddress": "f20171170@pilani.bits-pilani.ac.in",
"slug": "hypro999",
"id": 1,
"name": "hypro999"
},
"comment": {
"author": {
"active": true,
"type": "NORMAL",
"links": {
"self": [
{
"href": "http://139.59.64.214:7990/users/hypro999"
}
]
},
"displayName": "Hemanth V. Alluri",
"emailAddress": "f20171170@pilani.bits-pilani.ac.in",
"slug": "hypro999",
"id": 1,
"name": "hypro999"
},
"id": 1,
"updatedDate": 1553169751306,
"tasks": [],
"comments": [],
"version": 0,
"text": "Just an arbitrary comment on a commit.",
"createdDate": 1553169751306,
"properties": {
"repositoryId": 2
}
},
"commit": "508d1b67f1f8f3a25f543a030a7a178894aa9907",
"repository": {
"state": "AVAILABLE",
"links": {
"clone": [
{
"href": "ssh://git@139.59.64.214:7999/sbox/sandbox.git",
"name": "ssh"
},
{
"href": "http://139.59.64.214:7990/scm/sbox/sandbox.git",
"name": "http"
}
],
"self": [
{
"href": "http://139.59.64.214:7990/projects/SBOX/repos/sandbox/browse"
}
]
},
"forkable": true,
"slug": "sandbox",
"project": {
"key": "SBOX",
"public": false,
"links": {
"self": [
{
"href": "http://139.59.64.214:7990/projects/SBOX"
}
]
},
"id": 2,
"type": "NORMAL",
"name": "Sandbox"
},
"id": 2,
"scmId": "git",
"public": false,
"name": "sandbox",
"statusMessage": "Available"
},
"eventKey": "repo:comment:added",
"date": "2019-03-21T17:32:31+0530"
}

View File

@@ -0,0 +1,87 @@
{
"actor": {
"active": true,
"type": "NORMAL",
"links": {
"self": [
{
"href": "http://139.59.64.214:7990/users/hypro999"
}
]
},
"displayName": "Hemanth V. Alluri",
"emailAddress": "f20171170@pilani.bits-pilani.ac.in",
"slug": "hypro999",
"id": 1,
"name": "hypro999"
},
"comment": {
"author": {
"active": true,
"type": "NORMAL",
"links": {
"self": [
{
"href": "http://139.59.64.214:7990/users/hypro999"
}
]
},
"displayName": "Hemanth V. Alluri",
"emailAddress": "f20171170@pilani.bits-pilani.ac.in",
"slug": "hypro999",
"id": 1,
"name": "hypro999"
},
"id": 1,
"updatedDate": 1553169856827,
"tasks": [],
"comments": [],
"version": 1,
"text": "Just an arbitrary comment on a commit. Nothing to see here...",
"createdDate": 1553169751306
},
"commit": "508d1b67f1f8f3a25f543a030a7a178894aa9907",
"repository": {
"state": "AVAILABLE",
"links": {
"clone": [
{
"href": "ssh://git@139.59.64.214:7999/sbox/sandbox.git",
"name": "ssh"
},
{
"href": "http://139.59.64.214:7990/scm/sbox/sandbox.git",
"name": "http"
}
],
"self": [
{
"href": "http://139.59.64.214:7990/projects/SBOX/repos/sandbox/browse"
}
]
},
"forkable": true,
"slug": "sandbox",
"project": {
"key": "SBOX",
"public": false,
"links": {
"self": [
{
"href": "http://139.59.64.214:7990/projects/SBOX"
}
]
},
"id": 2,
"type": "NORMAL",
"name": "Sandbox"
},
"id": 2,
"scmId": "git",
"public": false,
"name": "sandbox",
"statusMessage": "Available"
},
"eventKey": "repo:comment:deleted",
"date": "2019-03-21T17:34:57+0530"
}

View File

@@ -0,0 +1,91 @@
{
"actor": {
"active": true,
"type": "NORMAL",
"links": {
"self": [
{
"href": "http://139.59.64.214:7990/users/hypro999"
}
]
},
"displayName": "Hemanth V. Alluri",
"emailAddress": "f20171170@pilani.bits-pilani.ac.in",
"slug": "hypro999",
"id": 1,
"name": "hypro999"
},
"comment": {
"author": {
"active": true,
"type": "NORMAL",
"links": {
"self": [
{
"href": "http://139.59.64.214:7990/users/hypro999"
}
]
},
"displayName": "Hemanth V. Alluri",
"emailAddress": "f20171170@pilani.bits-pilani.ac.in",
"slug": "hypro999",
"id": 1,
"name": "hypro999"
},
"id": 1,
"updatedDate": 1553169856827,
"tasks": [],
"comments": [],
"version": 1,
"text": "Just an arbitrary comment on a commit. Nothing to see here...",
"createdDate": 1553169751306,
"properties": {
"repositoryId": 2
}
},
"previousComment": "Just an arbitrary comment on a commit.",
"commit": "508d1b67f1f8f3a25f543a030a7a178894aa9907",
"repository": {
"state": "AVAILABLE",
"links": {
"clone": [
{
"href": "ssh://git@139.59.64.214:7999/sbox/sandbox.git",
"name": "ssh"
},
{
"href": "http://139.59.64.214:7990/scm/sbox/sandbox.git",
"name": "http"
}
],
"self": [
{
"href": "http://139.59.64.214:7990/projects/SBOX/repos/sandbox/browse"
}
]
},
"forkable": true,
"slug": "sandbox",
"project": {
"key": "SBOX",
"public": false,
"links": {
"self": [
{
"href": "http://139.59.64.214:7990/projects/SBOX"
}
]
},
"id": 2,
"type": "NORMAL",
"name": "Sandbox"
},
"id": 2,
"scmId": "git",
"public": false,
"name": "sandbox",
"statusMessage": "Available"
},
"eventKey": "repo:comment:edited",
"date": "2019-03-21T17:34:16+0530"
}

View File

@@ -0,0 +1,117 @@
{
"actor": {
"links": {
"self": [
{
"href": "http://139.59.64.214:7990/users/hypro999"
}
]
},
"displayName": "Hemanth V. Alluri",
"active": true,
"slug": "hypro999",
"type": "NORMAL",
"name": "hypro999",
"id": 1,
"emailAddress": "f20171170@pilani.bits-pilani.ac.in"
},
"repository": {
"links": {
"clone": [
{
"href": "ssh://git@139.59.64.214:7999/~hypro999/sandbox-fork.git",
"name": "ssh"
},
{
"href": "http://139.59.64.214:7990/scm/~hypro999/sandbox-fork.git",
"name": "http"
}
],
"self": [
{
"href": "http://139.59.64.214:7990/users/hypro999/repos/sandbox-fork/browse"
}
]
},
"statusMessage": "Available",
"id": 4,
"slug": "sandbox-fork",
"project": {
"links": {
"self": [
{
"href": "http://139.59.64.214:7990/users/hypro999"
}
]
},
"owner": {
"links": {
"self": [
{
"href": "http://139.59.64.214:7990/users/hypro999"
}
]
},
"displayName": "Hemanth V. Alluri",
"active": true,
"slug": "hypro999",
"type": "NORMAL",
"name": "hypro999",
"id": 1,
"emailAddress": "f20171170@pilani.bits-pilani.ac.in"
},
"key": "~HYPRO999",
"type": "PERSONAL",
"name": "Hemanth V. Alluri",
"id": 3
},
"origin": {
"links": {
"clone": [
{
"href": "ssh://git@139.59.64.214:7999/sbox/sandbox.git",
"name": "ssh"
},
{
"href": "http://139.59.64.214:7990/scm/sbox/sandbox.git",
"name": "http"
}
],
"self": [
{
"href": "http://139.59.64.214:7990/projects/SBOX/repos/sandbox/browse"
}
]
},
"statusMessage": "Available",
"id": 2,
"slug": "sandbox",
"project": {
"links": {
"self": [
{
"href": "http://139.59.64.214:7990/projects/SBOX"
}
]
},
"key": "SBOX",
"type": "NORMAL",
"name": "Sandbox",
"id": 2,
"public": false
},
"name": "sandbox",
"state": "AVAILABLE",
"forkable": true,
"scmId": "git",
"public": false
},
"name": "sandbox fork",
"state": "AVAILABLE",
"forkable": true,
"scmId": "git",
"public": false
},
"date": "2019-03-08T12:25:34+0530",
"eventKey": "repo:forked"
}

View File

@@ -0,0 +1,102 @@
{
"actor": {
"links": {
"self": [
{
"href": "http://139.59.64.214:7990/users/hypro999"
}
]
},
"displayName": "Hemanth V. Alluri",
"active": true,
"slug": "hypro999",
"type": "NORMAL",
"name": "hypro999",
"id": 1,
"emailAddress": "f20171170@pilani.bits-pilani.ac.in"
},
"old": {
"links": {
"clone": [
{
"href": "ssh://git@139.59.64.214:7999/sbox/sandbox-v2.git",
"name": "ssh"
},
{
"href": "http://139.59.64.214:7990/scm/sbox/sandbox-v2.git",
"name": "http"
}
],
"self": [
{
"href": "http://139.59.64.214:7990/projects/SBOX/repos/sandbox/browse"
}
]
},
"statusMessage": "Available",
"id": 2,
"slug": "sandbox",
"project": {
"links": {
"self": [
{
"href": "http://139.59.64.214:7990/projects/SBOX"
}
]
},
"key": "SBOX",
"type": "NORMAL",
"name": "Sandbox",
"id": 2,
"public": false
},
"name": "sandbox",
"state": "AVAILABLE",
"forkable": true,
"scmId": "git",
"public": false
},
"date": "2019-03-08T18:20:26+0530",
"eventKey": "repo:modified",
"new": {
"links": {
"clone": [
{
"href": "ssh://git@139.59.64.214:7999/sbox/sandbox-v2.git",
"name": "ssh"
},
{
"href": "http://139.59.64.214:7990/scm/sbox/sandbox-v2.git",
"name": "http"
}
],
"self": [
{
"href": "http://139.59.64.214:7990/projects/SBOX/repos/sandbox-v2/browse"
}
]
},
"statusMessage": "Available",
"id": 2,
"slug": "sandbox-v2",
"project": {
"links": {
"self": [
{
"href": "http://139.59.64.214:7990/projects/SBOX"
}
]
},
"key": "SBOX",
"type": "NORMAL",
"name": "Sandbox",
"id": 2,
"public": false
},
"name": "sandbox v2",
"state": "AVAILABLE",
"forkable": true,
"scmId": "git",
"public": false
}
}

View File

@@ -0,0 +1,74 @@
{
"repository": {
"state": "AVAILABLE",
"links": {
"clone": [
{
"href": "ssh://git@139.59.64.214:7999/sbox/sandbox.git",
"name": "ssh"
},
{
"href": "http://139.59.64.214:7990/scm/sbox/sandbox.git",
"name": "http"
}
],
"self": [
{
"href": "http://139.59.64.214:7990/projects/SBOX/repos/sandbox/browse"
}
]
},
"forkable": true,
"slug": "sandbox",
"project": {
"key": "SBOX",
"public": false,
"links": {
"self": [
{
"href": "http://139.59.64.214:7990/projects/SBOX"
}
]
},
"id": 2,
"type": "NORMAL",
"name": "Sandbox"
},
"id": 2,
"scmId": "git",
"public": false,
"name": "sandbox",
"statusMessage": "Available"
},
"actor": {
"active": true,
"type": "NORMAL",
"links": {
"self": [
{
"href": "http://139.59.64.214:7990/users/hypro999"
}
]
},
"displayName": "Hemanth V. Alluri",
"emailAddress": "f20171170@pilani.bits-pilani.ac.in",
"slug": "hypro999",
"id": 1,
"name": "hypro999"
},
"eventKey": "repo:refs_changed",
"date": "2019-03-21T09:37:33+0530",
"changes": [
{
"toHash": "c7fccd35e163571148c42a3e8b11aef6661d19b8",
"type": "ADD",
"ref": {
"type": "BRANCH",
"id": "refs/heads/branch2",
"displayId": "branch2"
},
"fromHash": "0000000000000000000000000000000000000000",
"refId": "refs/heads/branch2"
}
]
}

View File

@@ -0,0 +1,74 @@
{
"repository": {
"state": "AVAILABLE",
"links": {
"clone": [
{
"href": "ssh://git@139.59.64.214:7999/sbox/sandbox.git",
"name": "ssh"
},
{
"href": "http://139.59.64.214:7990/scm/sbox/sandbox.git",
"name": "http"
}
],
"self": [
{
"href": "http://139.59.64.214:7990/projects/SBOX/repos/sandbox/browse"
}
]
},
"forkable": true,
"slug": "sandbox",
"project": {
"key": "SBOX",
"public": false,
"links": {
"self": [
{
"href": "http://139.59.64.214:7990/projects/SBOX"
}
]
},
"id": 2,
"type": "NORMAL",
"name": "Sandbox"
},
"id": 2,
"scmId": "git",
"public": false,
"name": "sandbox",
"statusMessage": "Available"
},
"actor": {
"active": true,
"type": "NORMAL",
"links": {
"self": [
{
"href": "http://139.59.64.214:7990/users/hypro999"
}
]
},
"displayName": "Hemanth V. Alluri",
"emailAddress": "f20171170@pilani.bits-pilani.ac.in",
"slug": "hypro999",
"id": 1,
"name": "hypro999"
},
"eventKey": "repo:refs_changed",
"date": "2019-03-17T22:41:19+0530",
"changes": [
{
"toHash": "9b5565bec1d0e8d5d60d423fe70b54849d3aacc4",
"type": "ADD",
"ref": {
"type": "TAG",
"id": "refs/tags/newtag",
"displayId": "newtag"
},
"fromHash": "0000000000000000000000000000000000000000",
"refId": "refs/tags/newtag"
}
]
}

View File

@@ -0,0 +1,74 @@
{
"repository": {
"state": "AVAILABLE",
"links": {
"clone": [
{
"href": "ssh://git@139.59.64.214:7999/sbox/sandbox.git",
"name": "ssh"
},
{
"href": "http://139.59.64.214:7990/scm/sbox/sandbox.git",
"name": "http"
}
],
"self": [
{
"href": "http://139.59.64.214:7990/projects/SBOX/repos/sandbox/browse"
}
]
},
"forkable": true,
"slug": "sandbox",
"project": {
"key": "SBOX",
"public": false,
"links": {
"self": [
{
"href": "http://139.59.64.214:7990/projects/SBOX"
}
]
},
"id": 2,
"type": "NORMAL",
"name": "Sandbox"
},
"id": 2,
"scmId": "git",
"public": false,
"name": "sandbox",
"statusMessage": "Available"
},
"actor": {
"active": true,
"type": "NORMAL",
"links": {
"self": [
{
"href": "http://139.59.64.214:7990/users/hypro999"
}
]
},
"displayName": "Hemanth V. Alluri",
"emailAddress": "f20171170@pilani.bits-pilani.ac.in",
"slug": "hypro999",
"id": 1,
"name": "hypro999"
},
"eventKey": "repo:refs_changed",
"date": "2019-03-21T09:44:17+0530",
"changes": [
{
"toHash": "0000000000000000000000000000000000000000",
"type": "DELETE",
"ref": {
"type": "BRANCH",
"id": "refs/heads/branch2",
"displayId": "branch2"
},
"fromHash": "c7fccd35e163571148c42a3e8b11aef6661d19b8",
"refId": "refs/heads/branch2"
}
]
}

View File

@@ -0,0 +1,74 @@
{
"repository": {
"state": "AVAILABLE",
"links": {
"clone": [
{
"href": "ssh://git@139.59.64.214:7999/sbox/sandbox.git",
"name": "ssh"
},
{
"href": "http://139.59.64.214:7990/scm/sbox/sandbox.git",
"name": "http"
}
],
"self": [
{
"href": "http://139.59.64.214:7990/projects/SBOX/repos/sandbox/browse"
}
]
},
"forkable": true,
"slug": "sandbox",
"project": {
"key": "SBOX",
"public": false,
"links": {
"self": [
{
"href": "http://139.59.64.214:7990/projects/SBOX"
}
]
},
"id": 2,
"type": "NORMAL",
"name": "Sandbox"
},
"id": 2,
"scmId": "git",
"public": false,
"name": "sandbox",
"statusMessage": "Available"
},
"actor": {
"active": true,
"type": "NORMAL",
"links": {
"self": [
{
"href": "http://139.59.64.214:7990/users/hypro999"
}
]
},
"displayName": "Hemanth V. Alluri",
"emailAddress": "f20171170@pilani.bits-pilani.ac.in",
"slug": "hypro999",
"id": 1,
"name": "hypro999"
},
"eventKey": "repo:refs_changed",
"date": "2019-03-21T09:54:37+0530",
"changes": [
{
"toHash": "0000000000000000000000000000000000000000",
"type": "DELETE",
"ref": {
"type": "TAG",
"id": "refs/tags/test-tag",
"displayId": "test-tag"
},
"fromHash": "b223099667fb4f71dd4f6f7d61cd2b7cdb184b37",
"refId": "refs/tags/test-tag"
}
]
}

View File

@@ -0,0 +1,85 @@
{
"repository": {
"state": "AVAILABLE",
"links": {
"clone": [
{
"href": "ssh://git@139.59.64.214:7999/sbox/sandbox.git",
"name": "ssh"
},
{
"href": "http://139.59.64.214:7990/scm/sbox/sandbox.git",
"name": "http"
}
],
"self": [
{
"href": "http://139.59.64.214:7990/projects/SBOX/repos/sandbox/browse"
}
]
},
"forkable": true,
"slug": "sandbox",
"project": {
"key": "SBOX",
"public": false,
"links": {
"self": [
{
"href": "http://139.59.64.214:7990/projects/SBOX"
}
]
},
"id": 2,
"type": "NORMAL",
"name": "Sandbox"
},
"id": 2,
"scmId": "git",
"public": false,
"name": "sandbox",
"statusMessage": "Available"
},
"actor": {
"active": true,
"type": "NORMAL",
"links": {
"self": [
{
"href": "http://139.59.64.214:7990/users/hypro999"
}
]
},
"displayName": "Hemanth V. Alluri",
"emailAddress": "f20171170@pilani.bits-pilani.ac.in",
"slug": "hypro999",
"id": 1,
"name": "hypro999"
},
"eventKey": "repo:refs_changed",
"date": "2019-03-17T19:09:40+0530",
"changes": [
{
"toHash": "3980c2be32a7e23c795741d5dc1a2eecb9b85d6d",
"type": "UPDATE",
"ref": {
"type": "BRANCH",
"id": "refs/heads/branch1",
"displayId": "branch1"
},
"fromHash": "9e5afb9f11a396eae4bf24755505d931b530649a",
"refId": "refs/heads/branch1"
},
{
"toHash": "fc43d13cff1abb28631196944ba4fc4ad06a2cf2",
"type": "UPDATE",
"ref": {
"type": "BRANCH",
"id": "refs/heads/master",
"displayId": "master"
},
"fromHash": "cb2e368ba3aca8a510f89667ae97b56d6a323db7",
"refId": "refs/heads/master"
}
]
}

View File

@@ -0,0 +1,74 @@
{
"actor": {
"links": {
"self": [
{
"href": "http://139.59.64.214:7990/users/hypro999"
}
]
},
"displayName": "Hemanth V. Alluri",
"active": true,
"slug": "hypro999",
"type": "NORMAL",
"name": "hypro999",
"id": 1,
"emailAddress": "f20171170@pilani.bits-pilani.ac.in"
},
"repository": {
"links": {
"clone": [
{
"href": "ssh://git@139.59.64.214:7999/sbox/sandbox.git",
"name": "ssh"
},
{
"href": "http://139.59.64.214:7990/scm/sbox/sandbox.git",
"name": "http"
}
],
"self": [
{
"href": "http://139.59.64.214:7990/projects/SBOX/repos/sandbox/browse"
}
]
},
"statusMessage": "Available",
"id": 2,
"slug": "sandbox",
"project": {
"links": {
"self": [
{
"href": "http://139.59.64.214:7990/projects/SBOX"
}
]
},
"key": "SBOX",
"type": "NORMAL",
"name": "Sandbox",
"id": 2,
"public": false
},
"name": "sandbox",
"state": "AVAILABLE",
"forkable": true,
"scmId": "git",
"public": false
},
"date": "2019-03-17T18:15:52+0530",
"eventKey": "repo:refs_changed",
"changes": [
{
"ref": {
"id": "refs/heads/master",
"displayId": "master",
"type": "BRANCH"
},
"toHash": "e68c981ef53dbab0a5ca320a2d8d80e216c70528",
"refId": "refs/heads/master",
"fromHash": "7c4cae30d77990b9095024bdd6c7bf0d545d870b",
"type": "UPDATE"
}
]
}

View File

@@ -0,0 +1,110 @@
# -*- coding: utf-8 -*-
from zerver.lib.test_classes import WebhookTestCase
class Bitbucket3HookTests(WebhookTestCase):
STREAM_NAME = "bitbucket3"
URL_TEMPLATE = "/api/v1/external/bitbucket3?stream={stream}&api_key={api_key}"
FIXTURE_DIR_NAME = "bitbucket3"
EXPECTED_TOPIC = "sandbox"
EXPECTED_TOPIC_BRANCH_EVENTS = "sandbox / {branch}"
def test_commit_comment_added(self) -> None:
expected_message = """hypro999 commented on [508d1b6](http://139.59.64.214:7990/projects\
/SBOX/repos/sandbox/commits/508d1b67f1f8f3a25f543a030a7a178894aa9907)\n~~~ quote\nJust an \
arbitrary comment on a commit.\n~~~"""
self.send_and_test_stream_message("commit_comment_added",
self.EXPECTED_TOPIC,
expected_message)
def test_commit_comment_edited(self) -> None:
expected_message = """hypro999 edited their comment on [508d1b6](http://139.59.64.214:7990\
/projects/SBOX/repos/sandbox/commits/508d1b67f1f8f3a25f543a030a7a178894aa9907)\n~~~ quote\nJust \
an arbitrary comment on a commit. Nothing to see here...\n~~~"""
self.send_and_test_stream_message("commit_comment_edited",
self.EXPECTED_TOPIC,
expected_message)
def test_commit_comment_deleted(self) -> None:
expected_message = """hypro999 deleted their comment on [508d1b6]\
(http://139.59.64.214:7990/projects/SBOX/repos/sandbox/commits/508d1b67f1f8f3a25f543a030a7a178894a\
a9907)\n~~~ quote\nJust an arbitrary comment on a commit. Nothing to see here...\n~~~"""
self.send_and_test_stream_message("commit_comment_deleted",
self.EXPECTED_TOPIC,
expected_message)
def test_bitbucket3_repo_forked(self) -> None:
expected_message = """User Hemanth V. Alluri(login: hypro999) forked the repository into \
[sandbox fork](http://139.59.64.214:7990/users/hypro999/repos/sandbox-fork/browse)."""
self.send_and_test_stream_message("repo_forked", self.EXPECTED_TOPIC, expected_message)
def test_bitbucket3_repo_modified(self) -> None:
expected_message = """hypro999 changed the name of the **sandbox** repo from **sandbox** \
to **sandbox v2**"""
expected_topic = "sandbox v2"
self.send_and_test_stream_message("repo_modified", expected_topic, expected_message)
def test_push_add_branch(self) -> None:
expected_message = """hypro999 created branch2 branch"""
expected_topic = self.EXPECTED_TOPIC_BRANCH_EVENTS.format(branch="branch2")
self.send_and_test_stream_message("repo_push_add_branch",
expected_topic,
expected_message)
def test_push_add_tag(self) -> None:
expected_message = """hypro999 pushed tag newtag"""
self.send_and_test_stream_message("repo_push_add_tag",
self.EXPECTED_TOPIC,
expected_message)
def test_push_delete_branch(self) -> None:
expected_message = """hypro999 deleted branch branch2"""
expected_topic = self.EXPECTED_TOPIC_BRANCH_EVENTS.format(branch="branch2")
self.send_and_test_stream_message("repo_push_delete_branch",
expected_topic,
expected_message)
def test_push_delete_tag(self) -> None:
expected_message = """hypro999 removed tag test-tag"""
self.send_and_test_stream_message("repo_push_delete_tag",
self.EXPECTED_TOPIC,
expected_message)
def test_push_update_single_branch(self) -> None:
expected_message = """hypro999 pushed to branch master. Head is now \
e68c981ef53dbab0a5ca320a2d8d80e216c70528"""
expected_topic = self.EXPECTED_TOPIC_BRANCH_EVENTS.format(branch="master")
self.send_and_test_stream_message("repo_push_update_single_branch",
expected_topic,
expected_message)
def test_push_update_multiple_branches(self) -> None:
expected_message_first = """hypro999 pushed to branch branch1. Head is now \
3980c2be32a7e23c795741d5dc1a2eecb9b85d6d"""
expected_message_second = """hypro999 pushed to branch master. Head is now \
fc43d13cff1abb28631196944ba4fc4ad06a2cf2"""
self.send_and_test_stream_message("repo_push_update_multiple_branches")
msg = self.get_last_message()
self.do_test_topic(msg, self.EXPECTED_TOPIC_BRANCH_EVENTS.format(branch="master"))
self.do_test_message(msg, expected_message_second)
msg = self.get_second_to_last_message()
self.do_test_topic(msg, self.EXPECTED_TOPIC_BRANCH_EVENTS.format(branch="branch1"))
self.do_test_message(msg, expected_message_first)
def test_push_update_multiple_branches_with_branch_filter(self) -> None:
self.url = self.build_webhook_url(branches='master')
expected_message = """hypro999 pushed to branch master. Head is now \
fc43d13cff1abb28631196944ba4fc4ad06a2cf2"""
expected_topic = self.EXPECTED_TOPIC_BRANCH_EVENTS.format(branch="master")
self.send_and_test_stream_message("repo_push_update_multiple_branches",
expected_topic,
expected_message)
self.url = self.build_webhook_url(branches='branch1')
expected_message = """hypro999 pushed to branch branch1. Head is now \
3980c2be32a7e23c795741d5dc1a2eecb9b85d6d"""
expected_topic = self.EXPECTED_TOPIC_BRANCH_EVENTS.format(branch="branch1")
self.send_and_test_stream_message("repo_push_update_multiple_branches",
expected_topic,
expected_message)

View File

@@ -0,0 +1,163 @@
from inspect import signature
from functools import partial
from typing import Any, Dict, Optional, List, Callable
from django.http import HttpRequest, HttpResponse
from zerver.models import UserProfile
from zerver.decorator import api_key_only_webhook_view
from zerver.lib.request import REQ, has_request_variables
from zerver.lib.response import json_success
from zerver.lib.webhooks.git import TOPIC_WITH_BRANCH_TEMPLATE, \
get_push_tag_event_message, get_remove_branch_event_message, \
get_create_branch_event_message, get_commits_comment_action_message
from zerver.lib.webhooks.common import check_send_webhook_message, \
UnexpectedWebhookEventType
from zerver.webhooks.bitbucket2.view import BITBUCKET_TOPIC_TEMPLATE, \
BITBUCKET_FORK_BODY, BITBUCKET_REPO_UPDATED_CHANGED
BRANCH_UPDATED_MESSAGE_TEMPLATE = "{user_name} pushed to branch {branch_name}. Head is now {head}"
def repo_comment_handler(payload: Dict[str, Any], action: str) -> List[Dict[str, str]]:
repo_name = payload["repository"]["name"]
user_name = payload["actor"]["name"]
subject = BITBUCKET_TOPIC_TEMPLATE.format(repository_name=repo_name)
sha = payload["commit"]
commit_url = payload["repository"]["links"]["self"][0]["href"][:-6] # remove the "browse" at the end
commit_url += "commits/%s" % (sha,)
body = get_commits_comment_action_message(user_name=user_name,
action=action,
commit_url=commit_url,
sha=sha,
message=payload["comment"]["text"])
return [{"subject": subject, "body": body}]
def repo_forked_handler(payload: Dict[str, Any]) -> List[Dict[str, str]]:
repo_name = payload["repository"]["origin"]["name"]
subject = BITBUCKET_TOPIC_TEMPLATE.format(repository_name=repo_name)
body = BITBUCKET_FORK_BODY.format(
display_name=payload["actor"]["displayName"],
username=payload["actor"]["name"],
fork_name=payload["repository"]["name"],
fork_url=payload["repository"]["links"]["self"][0]["href"]
)
return [{"subject": subject, "body": body}]
def repo_modified_handler(payload: Dict[str, Any]) -> List[Dict[str, str]]:
subject_new = BITBUCKET_TOPIC_TEMPLATE.format(repository_name=payload["new"]["name"])
body = BITBUCKET_REPO_UPDATED_CHANGED.format(
actor=payload["actor"]["name"],
change="name",
repo_name=payload["old"]["name"],
old=payload["old"]["name"],
new=payload["new"]["name"]
) # As of writing this, the only change we'd be notified about is a name change.
return [{"subject": subject_new, "body": body}]
def repo_push_branch_data(payload: Dict[str, Any], change: Dict[str, Any]) -> Dict[str, str]:
event_type = change["type"]
repo_name = payload["repository"]["name"]
user_name = payload["actor"]["name"]
branch_name = change["ref"]["displayId"]
branch_head = change["toHash"]
if event_type == "ADD":
body = get_create_branch_event_message(user_name=user_name, url=None, branch_name=branch_name)
elif event_type == "UPDATE":
body = BRANCH_UPDATED_MESSAGE_TEMPLATE.format(user_name=user_name,
branch_name=branch_name,
head=branch_head)
elif event_type == "DELETE":
body = get_remove_branch_event_message(user_name, branch_name)
else:
message = "%s.%s" % (payload["eventKey"], event_type) # nocoverage
raise UnexpectedWebhookEventType("BitBucket Server", message)
subject = TOPIC_WITH_BRANCH_TEMPLATE.format(repo=repo_name, branch=branch_name)
return {"subject": subject, "body": body}
def repo_push_tag_data(payload: Dict[str, Any], change: Dict[str, Any]) -> Dict[str, str]:
event_type = change["type"]
repo_name = payload["repository"]["name"]
tag_name = change["ref"]["displayId"]
user_name = payload["actor"]["name"]
if event_type == "ADD":
action = "pushed"
elif event_type == "DELETE":
action = "removed"
else:
message = "%s.%s" % (payload["eventKey"], event_type) # nocoverage
raise UnexpectedWebhookEventType("BitBucket Server", message)
subject = BITBUCKET_TOPIC_TEMPLATE.format(repository_name=repo_name)
body = get_push_tag_event_message(
user_name,
tag_name,
action=action)
return {"subject": subject, "body": body}
def repo_push_handler(payload: Dict[str, Any], branches: Optional[str]=None) -> List[Dict[str, str]]:
data = []
for change in payload["changes"]:
event_target_type = change["ref"]["type"]
if event_target_type == "BRANCH":
branch = change["ref"]["displayId"]
if branches:
if branch not in branches:
continue
data.append(repo_push_branch_data(payload, change))
elif event_target_type == "TAG":
data.append(repo_push_tag_data(payload, change))
else:
message = "%s.%s" % (payload["eventKey"], event_target_type) # nocoverage
raise UnexpectedWebhookEventType("BitBucket Server", message)
return data
EVENT_HANDLER_MAP = {
"repo:comment:added": partial(repo_comment_handler, action="commented"),
"repo:comment:edited": partial(repo_comment_handler, action="edited their comment"),
"repo:comment:deleted": partial(repo_comment_handler, action="deleted their comment"),
"repo:forked": repo_forked_handler,
"repo:modified": repo_modified_handler,
"repo:refs_changed": repo_push_handler,
"pr:comment:added": None,
"pr:comment:edited": None,
"pr:comment:deleted": None,
"pr:declined": None,
"pr:deleted": None,
"pr:merged": None,
"pr:modified": None,
"pr:opened": None,
"pr:reviewer:approved": None,
"pr:reviewer:needs_work": None,
"pr:reviewer:updated": None,
"pr:reviewer:unapproved": None,
} # type Dict[str, Optional[Callable[..., List[Dict[str, str]]]]]
def get_event_handler(eventkey: str) -> Callable[..., List[Dict[str, str]]]:
# The main reason for this function existance is because of mypy
handler = EVENT_HANDLER_MAP.get(eventkey) # type: Any
if handler is None:
raise UnexpectedWebhookEventType("BitBucket Server", eventkey)
return handler
@api_key_only_webhook_view("Bitbucket3")
@has_request_variables
def api_bitbucket3_webhook(request: HttpRequest, user_profile: UserProfile,
payload: Dict[str, Any]=REQ(argument_type="body"),
branches: Optional[str]=REQ(default=None),
user_specified_topic: Optional[str]=REQ("topic", default=None)
) -> HttpResponse:
eventkey = payload["eventKey"]
handler = get_event_handler(eventkey)
if "branches" in signature(handler).parameters:
data = handler(payload, branches)
else:
data = handler(payload)
for element in data:
check_send_webhook_message(request, user_profile, element["subject"],
element["body"], unquote_url_parameters=True)
return json_success()