mirror of https://github.com/zulip/zulip.git
integrations: Add webhook code, API endpoint, and tests for Opbeat.
This commit is contained in:
parent
b0fb7aa6b2
commit
4e2b99a98b
|
@ -330,6 +330,13 @@ WEBHOOK_INTEGRATIONS = [
|
|||
WebhookIntegration('librato', ['monitoring']),
|
||||
WebhookIntegration('mention', ['marketing'], display_name='Mention'),
|
||||
WebhookIntegration('newrelic', ['monitoring'], display_name='New Relic'),
|
||||
WebhookIntegration(
|
||||
'opbeat',
|
||||
['monitoring'],
|
||||
display_name='Opbeat',
|
||||
stream_name='opbeat',
|
||||
function='zerver.webhooks.opbeat.view.api_opbeat_webhook'
|
||||
),
|
||||
WebhookIntegration('opsgenie', ['meta-integration', 'monitoring'], display_name='OpsGenie'),
|
||||
WebhookIntegration('pagerduty', ['monitoring']),
|
||||
WebhookIntegration('papertrail', ['monitoring']),
|
||||
|
|
|
@ -1,148 +0,0 @@
|
|||
{
|
||||
"id": "5df00003ea4e42458db48446692f6d37",
|
||||
"url": "https://opbeat.com/api/v2/organizations/f9a77c5e6b044c2686612539fe4a3a6f/activities/5df00003ea4e42458db48446692f6d37",
|
||||
"html_url": "https://opbeat.com/topkek/test-flask-app/errors/2/#activity-5df00003ea4e42458db48446692f6d37",
|
||||
"author": {
|
||||
"id": "5802edc6e84b4843b23edff00c6d300a",
|
||||
"legacy_id": 14883,
|
||||
"first_name": "Ivche",
|
||||
"last_name": "E",
|
||||
"email": "ivchepro@gmail.com",
|
||||
"avatar": {
|
||||
"40": "https://secure.gravatar.com/avatar/cf936cf5a05314e692830f4d17ec434e?d=https%3A%2F%2Fopbeat.com%2Fstatic%2Fimages%2Fcommon%2Favatars%2Favatar_default_user.png&size=40",
|
||||
"80": "https://secure.gravatar.com/avatar/cf936cf5a05314e692830f4d17ec434e?d=https%3A%2F%2Fopbeat.com%2Fstatic%2Fimages%2Fcommon%2Favatars%2Favatar_default_user.png&size=80",
|
||||
"180": "https://secure.gravatar.com/avatar/cf936cf5a05314e692830f4d17ec434e?d=https%3A%2F%2Fopbeat.com%2Fstatic%2Fimages%2Fcommon%2Favatars%2Favatar_default_user.png&size=180",
|
||||
"240": "https://secure.gravatar.com/avatar/cf936cf5a05314e692830f4d17ec434e?d=https%3A%2F%2Fopbeat.com%2Fstatic%2Fimages%2Fcommon%2Favatars%2Favatar_default_user.png&size=240",
|
||||
"120": "https://secure.gravatar.com/avatar/cf936cf5a05314e692830f4d17ec434e?d=https%3A%2F%2Fopbeat.com%2Fstatic%2Fimages%2Fcommon%2Favatars%2Favatar_default_user.png&size=120"
|
||||
},
|
||||
"html_url": "https://opbeat.com/account/settings/",
|
||||
"type_name": "user"
|
||||
},
|
||||
"created": "2017-12-10T18:14:23Z",
|
||||
"occurred": "2017-12-10T18:14:23Z",
|
||||
"title": "Ivche commented on E#2",
|
||||
"summary": "comment",
|
||||
"organization": {
|
||||
"id": "f9a77c5e6b044c2686612539fe4a3a6f",
|
||||
"name": "topkek",
|
||||
"short_name": "topkek",
|
||||
"url": "https://opbeat.com/api/v2/organizations/f9a77c5e6b044c2686612539fe4a3a6f",
|
||||
"type_name": "organization"
|
||||
},
|
||||
"app": {
|
||||
"id": "53daf84bfc",
|
||||
"name": "Test-flask-app",
|
||||
"short_name": "test-flask-app",
|
||||
"url": "https://opbeat.com/api/v2/organizations/f9a77c5e6b044c2686612539fe4a3a6f/apps/53daf84bfc",
|
||||
"type_name": "app"
|
||||
},
|
||||
"subject_type": "comment",
|
||||
"subject": {
|
||||
"id": "ca45bf96cd674b3eaa914251f0a08773",
|
||||
"created": "2017-12-10T18:14:23Z",
|
||||
"text": "comment",
|
||||
"html": "<p>comment</p>",
|
||||
"author": {
|
||||
"id": "5802edc6e84b4843b23edff00c6d300a",
|
||||
"legacy_id": 14883,
|
||||
"first_name": "Ivche",
|
||||
"last_name": "E",
|
||||
"email": "ivchepro@gmail.com",
|
||||
"avatar": {
|
||||
"40": "https://secure.gravatar.com/avatar/cf936cf5a05314e692830f4d17ec434e?d=https%3A%2F%2Fopbeat.com%2Fstatic%2Fimages%2Fcommon%2Favatars%2Favatar_default_user.png&size=40",
|
||||
"80": "https://secure.gravatar.com/avatar/cf936cf5a05314e692830f4d17ec434e?d=https%3A%2F%2Fopbeat.com%2Fstatic%2Fimages%2Fcommon%2Favatars%2Favatar_default_user.png&size=80",
|
||||
"180": "https://secure.gravatar.com/avatar/cf936cf5a05314e692830f4d17ec434e?d=https%3A%2F%2Fopbeat.com%2Fstatic%2Fimages%2Fcommon%2Favatars%2Favatar_default_user.png&size=180",
|
||||
"240": "https://secure.gravatar.com/avatar/cf936cf5a05314e692830f4d17ec434e?d=https%3A%2F%2Fopbeat.com%2Fstatic%2Fimages%2Fcommon%2Favatars%2Favatar_default_user.png&size=240",
|
||||
"120": "https://secure.gravatar.com/avatar/cf936cf5a05314e692830f4d17ec434e?d=https%3A%2F%2Fopbeat.com%2Fstatic%2Fimages%2Fcommon%2Favatars%2Favatar_default_user.png&size=120"
|
||||
},
|
||||
"html_url": "https://opbeat.com/account/settings/",
|
||||
"type_name": "user"
|
||||
},
|
||||
"html_url": "https://opbeat.com/topkek/test-flask-app/errors/2/#activity-5df00003ea4e42458db48446692f6d37",
|
||||
"subject_type": "errorgroup",
|
||||
"subject": {
|
||||
"id": "eac027998bc44fb0b2f6269eb0ab0418",
|
||||
"number": 2,
|
||||
"created": "2017-12-10T17:52:48Z",
|
||||
"first_seen": "2017-12-10T17:52:47Z",
|
||||
"last_seen": "2017-12-10T18:07:55Z",
|
||||
"times_seen": {
|
||||
"this_release": 10,
|
||||
"total": 10,
|
||||
"24h": 10.0,
|
||||
"72h": 10.0
|
||||
},
|
||||
"url": "https://opbeat.com/api/v2/organizations/f9a77c5e6b044c2686612539fe4a3a6f/apps/53daf84bfc/errorgroups/eac027998bc44fb0b2f6269eb0ab0418",
|
||||
"html_url": "https://opbeat.com/topkek/test-flask-app/errors/2/",
|
||||
"links": {
|
||||
"activities": "https://opbeat.com/api/v2/organizations/f9a77c5e6b044c2686612539fe4a3a6f/apps/53daf84bfc/errorgroups/eac027998bc44fb0b2f6269eb0ab0418/activities",
|
||||
"undo-mark-as-fixed": "https://opbeat.com/api/v2/organizations/f9a77c5e6b044c2686612539fe4a3a6f/apps/53daf84bfc/errorgroups/eac027998bc44fb0b2f6269eb0ab0418/actions/undo-mark-fixed",
|
||||
"mark-as-temporarily-ignored": "https://opbeat.com/api/v2/organizations/f9a77c5e6b044c2686612539fe4a3a6f/apps/53daf84bfc/errorgroups/eac027998bc44fb0b2f6269eb0ab0418/actions/temporarily-ignore",
|
||||
"comments": "https://opbeat.com/api/v2/organizations/f9a77c5e6b044c2686612539fe4a3a6f/apps/53daf84bfc/errorgroups/eac027998bc44fb0b2f6269eb0ab0418/comments",
|
||||
"mark-as-fixed": "https://opbeat.com/api/v2/organizations/f9a77c5e6b044c2686612539fe4a3a6f/apps/53daf84bfc/errorgroups/eac027998bc44fb0b2f6269eb0ab0418/actions/mark-fixed",
|
||||
"assignable-users": "https://opbeat.com/api/v2/organizations/f9a77c5e6b044c2686612539fe4a3a6f/apps/53daf84bfc/assignable-users",
|
||||
"undo-mark-as-ignored": "https://opbeat.com/api/v2/organizations/f9a77c5e6b044c2686612539fe4a3a6f/apps/53daf84bfc/errorgroups/eac027998bc44fb0b2f6269eb0ab0418/actions/undo-ignore",
|
||||
"mark-as-ignored": "https://opbeat.com/api/v2/organizations/f9a77c5e6b044c2686612539fe4a3a6f/apps/53daf84bfc/errorgroups/eac027998bc44fb0b2f6269eb0ab0418/actions/ignore",
|
||||
"undo-mark-as-temporarily-ignored": "https://opbeat.com/api/v2/organizations/f9a77c5e6b044c2686612539fe4a3a6f/apps/53daf84bfc/errorgroups/eac027998bc44fb0b2f6269eb0ab0418/actions/undo-temporarily-ignore",
|
||||
"assign": "https://opbeat.com/api/v2/organizations/f9a77c5e6b044c2686612539fe4a3a6f/apps/53daf84bfc/errorgroups/eac027998bc44fb0b2f6269eb0ab0418/actions/assign"
|
||||
},
|
||||
"last_occurrence": {
|
||||
"id": "24210da90e5b4d659965b2e3ebf360f4",
|
||||
"created": "2017-12-10T18:07:55Z",
|
||||
"culprit": "",
|
||||
"message": "A warning occurred (42 apples)",
|
||||
"logger": "__main__",
|
||||
"client_supplied_id": "13a4410d11724b30af92cd6ef1d556e8",
|
||||
"extra": {
|
||||
"thread": "140621113497408",
|
||||
"process": "6120",
|
||||
"threadName": "MainThread",
|
||||
"stack_info": "None",
|
||||
"module": "app",
|
||||
"funcName": "foo",
|
||||
"processName": "MainProcess",
|
||||
"pathname": "app.py",
|
||||
"lineno": "17",
|
||||
"message": "A warning occurred (42 apples)",
|
||||
"filename": "app.py"
|
||||
},
|
||||
"type_name": "errorlog"
|
||||
},
|
||||
"resolved_state": "regressed",
|
||||
"allowed_resolve_transitions": [
|
||||
"mark-as-temporarily-ignored",
|
||||
"mark-as-fixed",
|
||||
"mark-as-ignored"
|
||||
],
|
||||
"is_alarm": false,
|
||||
"num_comments": 4,
|
||||
"is_expired": false,
|
||||
"type_name": "errorgroup",
|
||||
"first_error": {
|
||||
"id": "24210da90e5b4d659965b2e3ebf360f4",
|
||||
"created": "2017-12-10T18:07:55Z",
|
||||
"culprit": "",
|
||||
"message": "A warning occurred (42 apples)",
|
||||
"logger": "__main__",
|
||||
"client_supplied_id": "13a4410d11724b30af92cd6ef1d556e8",
|
||||
"extra": {
|
||||
"thread": "140621113497408",
|
||||
"process": "6120",
|
||||
"threadName": "MainThread",
|
||||
"stack_info": "None",
|
||||
"module": "app",
|
||||
"funcName": "foo",
|
||||
"processName": "MainProcess",
|
||||
"pathname": "app.py",
|
||||
"lineno": "17",
|
||||
"message": "A warning occurred (42 apples)",
|
||||
"filename": "app.py"
|
||||
},
|
||||
"type_name": "errorlog"
|
||||
}
|
||||
},
|
||||
"type_name": "comment"
|
||||
},
|
||||
"action": "created",
|
||||
"type_name": "activity"
|
||||
}
|
|
@ -1,11 +1,11 @@
|
|||
{
|
||||
"id": "bf991a45d9184b0ca6fb3d48d3db4c38",
|
||||
"url": "https://opbeat.com/api/v2/organizations/f9a77c5e6b044c2686612539fe4a3a6f/activities/bf991a45d9184b0ca6fb3d48d3db4c38",
|
||||
"html_url": "https://opbeat.com/topkek/test-flask-app/errors/2/#activity-bf991a45d9184b0ca6fb3d48d3db4c38",
|
||||
"html_url": "https://opbeat.com/test_org/test-flask-app/errors/2/#activity-bf991a45d9184b0ca6fb3d48d3db4c38",
|
||||
"author": {
|
||||
"id": "5802edc6e84b4843b23edff00c6d300a",
|
||||
"legacy_id": 14883,
|
||||
"first_name": "Ivche",
|
||||
"first_name": "foo",
|
||||
"last_name": "E",
|
||||
"email": "ivchepro@gmail.com",
|
||||
"avatar": {
|
||||
|
@ -20,12 +20,12 @@
|
|||
},
|
||||
"created": "2017-12-10T18:15:07Z",
|
||||
"occurred": "2017-12-10T18:15:07Z",
|
||||
"title": "Ivche marked E#2 as fixed",
|
||||
"summary": "Ivche marked the error group as fixed",
|
||||
"title": "foo marked E#2 as fixed",
|
||||
"summary": "foo marked the error group as fixed",
|
||||
"organization": {
|
||||
"id": "f9a77c5e6b044c2686612539fe4a3a6f",
|
||||
"name": "topkek",
|
||||
"short_name": "topkek",
|
||||
"name": "test_org",
|
||||
"short_name": "test_org",
|
||||
"url": "https://opbeat.com/api/v2/organizations/f9a77c5e6b044c2686612539fe4a3a6f",
|
||||
"type_name": "organization"
|
||||
},
|
||||
|
@ -50,7 +50,7 @@
|
|||
"72h": 10.0
|
||||
},
|
||||
"url": "https://opbeat.com/api/v2/organizations/f9a77c5e6b044c2686612539fe4a3a6f/apps/53daf84bfc/errorgroups/eac027998bc44fb0b2f6269eb0ab0418",
|
||||
"html_url": "https://opbeat.com/topkek/test-flask-app/errors/2/",
|
||||
"html_url": "https://opbeat.com/test_org/test-flask-app/errors/2/",
|
||||
"links": {
|
||||
"activities": "https://opbeat.com/api/v2/organizations/f9a77c5e6b044c2686612539fe4a3a6f/apps/53daf84bfc/errorgroups/eac027998bc44fb0b2f6269eb0ab0418/activities",
|
||||
"undo-mark-as-fixed": "https://opbeat.com/api/v2/organizations/f9a77c5e6b044c2686612539fe4a3a6f/apps/53daf84bfc/errorgroups/eac027998bc44fb0b2f6269eb0ab0418/actions/undo-mark-fixed",
|
|
@ -1,11 +1,11 @@
|
|||
{
|
||||
"id": "38a556dfc0b04a59a586359bbce1463d",
|
||||
"url": "https://opbeat.com/api/v2/organizations/f9a77c5e6b044c2686612539fe4a3a6f/activities/38a556dfc0b04a59a586359bbce1463d",
|
||||
"html_url": "https://opbeat.com/topkek/test-flask-app/errors/2/#activity-38a556dfc0b04a59a586359bbce1463d",
|
||||
"html_url": "https://opbeat.com/test_org/test-flask-app/errors/2/#activity-38a556dfc0b04a59a586359bbce1463d",
|
||||
"author": {
|
||||
"id": "5802edc6e84b4843b23edff00c6d300a",
|
||||
"legacy_id": 14883,
|
||||
"first_name": "Ivche",
|
||||
"first_name": "foo",
|
||||
"last_name": "E",
|
||||
"email": "ivchepro@gmail.com",
|
||||
"avatar": {
|
||||
|
@ -20,12 +20,12 @@
|
|||
},
|
||||
"created": "2017-12-10T18:15:39Z",
|
||||
"occurred": "2017-12-10T18:15:39Z",
|
||||
"title": "Ivche reopened E#2",
|
||||
"summary": "Ivche reopened the error group",
|
||||
"title": "foo reopened E#2",
|
||||
"summary": "foo reopened the error group",
|
||||
"organization": {
|
||||
"id": "f9a77c5e6b044c2686612539fe4a3a6f",
|
||||
"name": "topkek",
|
||||
"short_name": "topkek",
|
||||
"name": "test_org",
|
||||
"short_name": "test_org",
|
||||
"url": "https://opbeat.com/api/v2/organizations/f9a77c5e6b044c2686612539fe4a3a6f",
|
||||
"type_name": "organization"
|
||||
},
|
||||
|
@ -50,7 +50,7 @@
|
|||
"72h": 10.0
|
||||
},
|
||||
"url": "https://opbeat.com/api/v2/organizations/f9a77c5e6b044c2686612539fe4a3a6f/apps/53daf84bfc/errorgroups/eac027998bc44fb0b2f6269eb0ab0418",
|
||||
"html_url": "https://opbeat.com/topkek/test-flask-app/errors/2/",
|
||||
"html_url": "https://opbeat.com/test_org/test-flask-app/errors/2/",
|
||||
"links": {
|
||||
"activities": "https://opbeat.com/api/v2/organizations/f9a77c5e6b044c2686612539fe4a3a6f/apps/53daf84bfc/errorgroups/eac027998bc44fb0b2f6269eb0ab0418/activities",
|
||||
"undo-mark-as-fixed": "https://opbeat.com/api/v2/organizations/f9a77c5e6b044c2686612539fe4a3a6f/apps/53daf84bfc/errorgroups/eac027998bc44fb0b2f6269eb0ab0418/actions/undo-mark-fixed",
|
|
@ -0,0 +1,37 @@
|
|||
{
|
||||
"id": "47f1f10158d94cbf93a0b539abc64b0f",
|
||||
"html_url": null,
|
||||
"title": "foo",
|
||||
"summary": "App foo created",
|
||||
"organization": {
|
||||
"id": "27a4c0633f5c4a24a15a8896754145c4",
|
||||
"name": "bar",
|
||||
"short_name": "bar",
|
||||
"url": "https://opbeat.com/api/v2/organizations/27a4c0633f5c4a24a15a8896754145c4",
|
||||
"type_name": "organization"
|
||||
},
|
||||
"app": {
|
||||
"id": "bdb4751769",
|
||||
"name": "foo",
|
||||
"short_name": "foo",
|
||||
"url": "https://opbeat.com/api/v2/organizations/27a4c0633f5c4a24a15a8896754145c4/apps/bdb4751769",
|
||||
"type_name": "app"
|
||||
},
|
||||
"subject_type": "app",
|
||||
"subject": {
|
||||
"id": "bdb4751769",
|
||||
"created": "2018-01-03T11:16:49Z",
|
||||
"name": "foo",
|
||||
"short_name": "foo",
|
||||
"settings": null,
|
||||
"url": "https://opbeat.com/api/v2/organizations/27a4c0633f5c4a24a15a8896754145c4/apps/bdb4751769",
|
||||
"html_url": "/bar/foo/",
|
||||
"has_unread_notifications": false,
|
||||
"has_metrics_available": false,
|
||||
"language": "nodejs",
|
||||
"framework": "custom",
|
||||
"type_name": "app"
|
||||
},
|
||||
"action": "created",
|
||||
"type_name": "activity"
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
{
|
||||
"id": "5df00003ea4e42458db48446692f6d37",
|
||||
"html_url": "https://opbeat.com/foo/test-flask-app/errors/2/#activity-5df00003ea4e42458db48446692f6d37",
|
||||
"author": {
|
||||
"first_name": "foo",
|
||||
"last_name": "bar"
|
||||
},
|
||||
"title": "foo commented on E#2",
|
||||
"summary": "test comment",
|
||||
"subject_type": "comment",
|
||||
"subject": {
|
||||
"id": "ca45bf96cd674b3eaa914251f0a08773",
|
||||
"text": "test comment",
|
||||
"author": {
|
||||
"id": "5802edc6e84b4843b23edff00c6d300a",
|
||||
"first_name": "foo",
|
||||
"last_name": "barE"
|
||||
},
|
||||
"html_url": "https://opbeat.com/foo/test-flask-app/errors/2/#activity-5df00003ea4e42458db48446692f6d37",
|
||||
"subject_type": "errorgroup",
|
||||
"subject": {
|
||||
"id": "eac027998bc44fb0b2f6269eb0ab0418",
|
||||
"number": 2,
|
||||
"html_url": "https://opbeat.com/foo/test-flask-app/errors/2/",
|
||||
"last_occurrence": {
|
||||
"id": "24210da90e5b4d659965b2e3ebf360f4",
|
||||
"created": "2017-12-10T18:07:55Z",
|
||||
"culprit": "",
|
||||
"message": "A warning occurred (42 apples)",
|
||||
"logger": "__main__",
|
||||
"client_supplied_id": "13a4410d11724b30af92cd6ef1d556e8",
|
||||
"extra": {
|
||||
"module": "app",
|
||||
"funcName": "foo",
|
||||
"processName": "MainProcess",
|
||||
"pathname": "app.py",
|
||||
"lineno": "17",
|
||||
"message": "A warning occurred (42 apples)"
|
||||
},
|
||||
"type_name": "errorlog"
|
||||
}
|
||||
},
|
||||
"type_name": "comment"
|
||||
},
|
||||
"action": "created",
|
||||
"type_name": "activity"
|
||||
}
|
|
@ -2,15 +2,15 @@
|
|||
{
|
||||
"id": "c0396f38323a4fa7b314f87d5ed9cdd2",
|
||||
"url": "https://opbeat.com/api/v2/organizations/f9a77c5e6b044c2686612539fe4a3a6f/activities/c0396f38323a4fa7b314f87d5ed9cdd2",
|
||||
"html_url": "https://opbeat.com/topkek/test-flask-app/errors/2/#activity-c0396f38323a4fa7b314f87d5ed9cdd2",
|
||||
"html_url": "https://opbeat.com/test_org/test-flask-app/errors/2/#activity-c0396f38323a4fa7b314f87d5ed9cdd2",
|
||||
"created": "2017-12-10T18:07:55Z",
|
||||
"occurred": "2017-12-10T18:07:55Z",
|
||||
"title": "E#2 regressed",
|
||||
"summary": "The error group regressed",
|
||||
"organization": {
|
||||
"id": "f9a77c5e6b044c2686612539fe4a3a6f",
|
||||
"name": "topkek",
|
||||
"short_name": "topkek",
|
||||
"name": "test_org",
|
||||
"short_name": "test_org",
|
||||
"url": "https://opbeat.com/api/v2/organizations/f9a77c5e6b044c2686612539fe4a3a6f",
|
||||
"type_name": "organization"
|
||||
},
|
||||
|
@ -35,7 +35,7 @@
|
|||
"72h": 10.0
|
||||
},
|
||||
"url": "https://opbeat.com/api/v2/organizations/f9a77c5e6b044c2686612539fe4a3a6f/apps/53daf84bfc/errorgroups/eac027998bc44fb0b2f6269eb0ab0418",
|
||||
"html_url": "https://opbeat.com/topkek/test-flask-app/errors/2/",
|
||||
"html_url": "https://opbeat.com/test_org/test-flask-app/errors/2/",
|
||||
"links": {
|
||||
"activities": "https://opbeat.com/api/v2/organizations/f9a77c5e6b044c2686612539fe4a3a6f/apps/53daf84bfc/errorgroups/eac027998bc44fb0b2f6269eb0ab0418/activities",
|
||||
"undo-mark-as-fixed": "https://opbeat.com/api/v2/organizations/f9a77c5e6b044c2686612539fe4a3a6f/apps/53daf84bfc/errorgroups/eac027998bc44fb0b2f6269eb0ab0418/actions/undo-mark-fixed",
|
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
"id": "47f1f10158d94cbf93a0b539abc64b0f",
|
||||
"html_url": null,
|
||||
"title": "test title",
|
||||
"summary": "test summary",
|
||||
"organization": {
|
||||
"id": "27a4c0633f5c4a24a15a8896754145c4",
|
||||
"name": "bar",
|
||||
"short_name": "bar",
|
||||
"url": "https://opbeat.com/api/v2/organizations/27a4c0633f5c4a24a15a8896754145c4",
|
||||
"type_name": "organization"
|
||||
},
|
||||
"app": {
|
||||
"id": "bdb4751769",
|
||||
"name": "foo",
|
||||
"short_name": "foo",
|
||||
"url": "https://opbeat.com/api/v2/organizations/27a4c0633f5c4a24a15a8896754145c4/apps/bdb4751769",
|
||||
"type_name": "app"
|
||||
},
|
||||
"subject_type": "foo",
|
||||
"subject": {
|
||||
"id": "bdb4751769",
|
||||
"created": "2018-01-03T11:16:49Z",
|
||||
"name": "foo",
|
||||
"short_name": "foo",
|
||||
"settings": null
|
||||
},
|
||||
"action": "created",
|
||||
"type_name": "activity"
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from typing import Text
|
||||
|
||||
from zerver.lib.test_classes import WebhookTestCase
|
||||
from zerver.webhooks.opbeat.view import get_value
|
||||
|
||||
|
||||
class OpbeatHookTests(WebhookTestCase):
|
||||
STREAM_NAME = 'opbeat'
|
||||
URL_TEMPLATE = u"/api/v1/external/opbeat?api_key={api_key}"
|
||||
FIXTURE_DIR_NAME = 'opbeat'
|
||||
|
||||
def test_comment(self) -> None:
|
||||
expected_subject = "foo commented on E#2"
|
||||
expected_message = '''
|
||||
**[foo commented on E#2](https://opbeat.com/foo/test-flask-app/errors/2/#activity-5df00003ea4e42458db48446692f6d37)**
|
||||
test comment
|
||||
|
||||
|
||||
**[E#2](https://opbeat.com/foo/test-flask-app/errors/2/)**
|
||||
|
||||
>**Most recent Occurrence**
|
||||
>in app.py
|
||||
>A warning occurred (42 apples)'''
|
||||
self.send_and_test_stream_message('new_comment', expected_subject, expected_message,
|
||||
content_type="application/json")
|
||||
|
||||
def test_new_app(self) -> None:
|
||||
expected_subject = "foo"
|
||||
expected_message = '''
|
||||
**foo**
|
||||
App foo created
|
||||
|
||||
**[foo](https://opbeat.com/bar/foo/)**
|
||||
>language: nodejs
|
||||
>framework: custom'''
|
||||
self.send_and_test_stream_message('new_app', expected_subject, expected_message,
|
||||
content_type="application/json")
|
||||
|
||||
def test_get_empty_value(self) -> None:
|
||||
self.assertEqual(get_value({'key': 'value'}, 'foo'), '')
|
||||
|
||||
def test_no_subject_type(self) -> None:
|
||||
expected_subject = "test title"
|
||||
expected_message = '''
|
||||
**test title**
|
||||
test summary'''
|
||||
self.send_and_test_stream_message(
|
||||
'unsupported_object',
|
||||
expected_subject,
|
||||
expected_message,
|
||||
content_type='application/json'
|
||||
)
|
||||
|
||||
def test_error_fixed(self) -> None:
|
||||
expected_subject = 'foo marked E#2 as fixed'
|
||||
expected_message = '''
|
||||
**[foo marked E#2 as fixed](https://opbeat.com/test_org/test-flask-app/errors/2/#activity-bf991a45d9184b0ca6fb3d48d3db4c38)**
|
||||
foo marked the error group as fixed
|
||||
|
||||
**[E#2](https://opbeat.com/test_org/test-flask-app/errors/2/)**
|
||||
|
||||
>**Most recent Occurrence**
|
||||
>in app.py
|
||||
>A warning occurred (42 apples)'''
|
||||
self.send_and_test_stream_message(
|
||||
'error_fixed', expected_subject, expected_message, content_type='application/json')
|
||||
|
||||
def test_error_reopened(self) -> None:
|
||||
expected_subject = 'foo reopened E#2'
|
||||
expected_message = '''
|
||||
**[foo reopened E#2](https://opbeat.com/test_org/test-flask-app/errors/2/#activity-38a556dfc0b04a59a586359bbce1463d)**
|
||||
foo reopened the error group
|
||||
|
||||
**[E#2](https://opbeat.com/test_org/test-flask-app/errors/2/)**
|
||||
|
||||
>**Most recent Occurrence**
|
||||
>in app.py
|
||||
>A warning occurred (42 apples)'''
|
||||
self.send_and_test_stream_message(
|
||||
'error_reopen', expected_subject, expected_message, content_type='application/json')
|
||||
|
||||
def test_error_regressed(self) -> None:
|
||||
expected_subject = 'E#2 regressed'
|
||||
expected_message = '''
|
||||
**[E#2 regressed](https://opbeat.com/test_org/test-flask-app/errors/2/#activity-c0396f38323a4fa7b314f87d5ed9cdd2)**
|
||||
The error group regressed
|
||||
|
||||
**[E#2](https://opbeat.com/test_org/test-flask-app/errors/2/)**
|
||||
|
||||
>**Most recent Occurrence**
|
||||
>in app.py
|
||||
>A warning occurred (42 apples)'''
|
||||
self.send_and_test_stream_message(
|
||||
'new_error', expected_subject, expected_message, content_type='application/json')
|
|
@ -0,0 +1,120 @@
|
|||
# Webhooks for external integrations.
|
||||
from typing import Text, Dict, Any, List, Tuple, Union
|
||||
|
||||
from django.http import HttpRequest, HttpResponse
|
||||
|
||||
from zerver.decorator import api_key_only_webhook_view
|
||||
from zerver.lib.actions import check_send_stream_message
|
||||
from zerver.lib.request import REQ, has_request_variables
|
||||
from zerver.lib.response import json_success
|
||||
from zerver.models import UserProfile, get_client
|
||||
|
||||
subject_types = {
|
||||
'app': [ # Object type name
|
||||
['name'], # Title
|
||||
['html_url'], # Automatically put into title
|
||||
['language'], # Other properties.
|
||||
['framework']
|
||||
],
|
||||
'base': [
|
||||
['title'],
|
||||
['html_url'],
|
||||
['#summary'],
|
||||
['subject']
|
||||
],
|
||||
'comment': [
|
||||
[''],
|
||||
['subject']
|
||||
],
|
||||
'errorgroup': [
|
||||
['E#{}', 'number'],
|
||||
['html_url'],
|
||||
['last_occurrence:error']
|
||||
],
|
||||
'error': [
|
||||
[''],
|
||||
['">**Most recent Occurrence**'],
|
||||
['in {}', 'extra/pathname'],
|
||||
['!message']
|
||||
]
|
||||
} # type: Dict[str, List[List[str]]]
|
||||
|
||||
|
||||
def get_value(_obj: Dict[str, Any], key: str) -> str:
|
||||
for _key in key.lstrip('!').split('/'):
|
||||
if _key in _obj.keys():
|
||||
_obj = _obj[_key]
|
||||
else:
|
||||
return ''
|
||||
return str(_obj)
|
||||
|
||||
|
||||
def format_object(
|
||||
obj: Dict[str, Any],
|
||||
subject_type: str,
|
||||
message: str
|
||||
) -> str:
|
||||
if subject_type not in subject_types.keys():
|
||||
return message
|
||||
keys = subject_types[subject_type][1:] # type: List[List[str]]
|
||||
title = subject_types[subject_type][0]
|
||||
if title[0] != '':
|
||||
title_str = ''
|
||||
if len(title) > 1:
|
||||
title_str = title[0].format(get_value(obj, title[1]))
|
||||
else:
|
||||
title_str = obj[title[0]]
|
||||
if obj['html_url'] is not None:
|
||||
url = obj['html_url'] # type: str
|
||||
if 'opbeat.com' not in url:
|
||||
url = 'https://opbeat.com/' + url.lstrip('/')
|
||||
message += '\n**[{}]({})**'.format(title_str, url)
|
||||
else:
|
||||
message += '\n**{}**'.format(title_str)
|
||||
for key_list in keys:
|
||||
if len(key_list) > 1:
|
||||
value = key_list[0].format(get_value(obj, key_list[1]))
|
||||
message += '\n>{}'.format(value)
|
||||
else:
|
||||
key = key_list[0]
|
||||
key_raw = key.lstrip('!').lstrip('#').lstrip('"')
|
||||
if key_raw != 'html_url' and key_raw != 'subject' and ':' not in key_raw:
|
||||
value = get_value(obj, key_raw)
|
||||
if key.startswith('!'):
|
||||
message += '\n>{}'.format(value)
|
||||
elif key.startswith('#'):
|
||||
message += '\n{}'.format(value)
|
||||
elif key.startswith('"'):
|
||||
message += '\n{}'.format(key_raw)
|
||||
else:
|
||||
message += '\n>{}: {}'.format(key, value)
|
||||
if key == 'subject':
|
||||
message = format_object(
|
||||
obj['subject'], obj['subject_type'], message + '\n')
|
||||
if ':' in key:
|
||||
value, value_type = key.split(':')
|
||||
message = format_object(obj[value], value_type, message + '\n')
|
||||
return message
|
||||
|
||||
|
||||
@api_key_only_webhook_view("Opbeat")
|
||||
@has_request_variables
|
||||
def api_opbeat_webhook(
|
||||
request: HttpRequest,
|
||||
user_profile: UserProfile,
|
||||
payload: Dict[str, Any]=REQ(argument_type='body'),
|
||||
stream: str=REQ(default="opbeat")
|
||||
) -> HttpResponse:
|
||||
"""
|
||||
This uses the subject name from opbeat to make the subject,
|
||||
and the summary from Opbeat as the message body, with
|
||||
details about the object mentioned.
|
||||
"""
|
||||
|
||||
message_subject = payload['title']
|
||||
|
||||
message = format_object(payload, 'base', '')
|
||||
|
||||
check_send_stream_message(user_profile, get_client('ZulipOpbeatWebhook'),
|
||||
stream, message_subject, message)
|
||||
return json_success()
|
Loading…
Reference in New Issue