snapshot of https://github.com/zulip/zulip.git @ 48c69911c7dd4e03b20552eb3bd77ad8151c1357 (2026-09-15)
Some checks failed
Code scanning / CodeQL (push) Failing after 15s
Zulip production suite / Ubuntu 22.04 production build (push) Failing after 26s
Zulip production suite / Debian 12 production install with custom db name and user (push) Has been skipped
Zulip production suite / Ubuntu 22.04 production install and PostgreSQL upgrade with pgroonga (push) Has been skipped
Zulip production suite / Ubuntu 24.04 production install (push) Has been skipped
Zulip production suite / Ubuntu 26.04 production install (push) Has been skipped
Zulip production suite / Debian 13 production install (push) Has been skipped
Zulip production suite / 7.0 Version Upgrade (push) Has been skipped
Zulip production suite / 8.0 Version Upgrade (push) Has been skipped
Zulip production suite / 6.0 Version Upgrade (push) Has been skipped
Zulip production suite / 10.0 Version Upgrade (push) Has been skipped
Zulip production suite / 9.0 Version Upgrade (push) Has been skipped
Zulip production suite / 12.0 Version Upgrade (push) Has been skipped
Zulip production suite / 11.0 Version Upgrade (push) Has been skipped
GitHub Actions Security Analysis with zizmor / zizmor (push) Failing after 3s
Zulip CI / Debian 12 (Python 3.11, backend + documentation) (push) Failing after 26s
Zulip CI / Ubuntu 22.04 (Python 3.10, backend + frontend) (push) Failing after 3s
Zulip CI / Ubuntu 24.04 (Python 3.12, backend) (push) Failing after 25s
Zulip CI / Ubuntu 26.04 (Python 3.14, backend) (push) Failing after 25s
Zulip CI / Debian 13 (Python 3.13, backend) (push) Failing after 28s
Zulip production suite / Required jobs (push) Has been cancelled
Zulip CI / Required jobs (push) Has been cancelled
API Documentation Update Check / check-feature-level-updated (push) Has been cancelled
API Documentation Update Check / notify-if-api-docs-changed (push) Has been cancelled
Some checks failed
Code scanning / CodeQL (push) Failing after 15s
Zulip production suite / Ubuntu 22.04 production build (push) Failing after 26s
Zulip production suite / Debian 12 production install with custom db name and user (push) Has been skipped
Zulip production suite / Ubuntu 22.04 production install and PostgreSQL upgrade with pgroonga (push) Has been skipped
Zulip production suite / Ubuntu 24.04 production install (push) Has been skipped
Zulip production suite / Ubuntu 26.04 production install (push) Has been skipped
Zulip production suite / Debian 13 production install (push) Has been skipped
Zulip production suite / 7.0 Version Upgrade (push) Has been skipped
Zulip production suite / 8.0 Version Upgrade (push) Has been skipped
Zulip production suite / 6.0 Version Upgrade (push) Has been skipped
Zulip production suite / 10.0 Version Upgrade (push) Has been skipped
Zulip production suite / 9.0 Version Upgrade (push) Has been skipped
Zulip production suite / 12.0 Version Upgrade (push) Has been skipped
Zulip production suite / 11.0 Version Upgrade (push) Has been skipped
GitHub Actions Security Analysis with zizmor / zizmor (push) Failing after 3s
Zulip CI / Debian 12 (Python 3.11, backend + documentation) (push) Failing after 26s
Zulip CI / Ubuntu 22.04 (Python 3.10, backend + frontend) (push) Failing after 3s
Zulip CI / Ubuntu 24.04 (Python 3.12, backend) (push) Failing after 25s
Zulip CI / Ubuntu 26.04 (Python 3.14, backend) (push) Failing after 25s
Zulip CI / Debian 13 (Python 3.13, backend) (push) Failing after 28s
Zulip production suite / Required jobs (push) Has been cancelled
Zulip CI / Required jobs (push) Has been cancelled
API Documentation Update Check / check-feature-level-updated (push) Has been cancelled
API Documentation Update Check / notify-if-api-docs-changed (push) Has been cancelled
This commit is contained in:
0
zerver/webhooks/rundeck/__init__.py
Normal file
0
zerver/webhooks/rundeck/__init__.py
Normal file
29
zerver/webhooks/rundeck/doc.md
Normal file
29
zerver/webhooks/rundeck/doc.md
Normal file
@@ -0,0 +1,29 @@
|
||||
# Zulip Rundeck integration
|
||||
|
||||
Receive Rundeck job notifications in Zulip!
|
||||
|
||||
{start_tabs}
|
||||
|
||||
1. {!create-an-incoming-webhook.md!}
|
||||
|
||||
1. {!generate-webhook-url-basic.md!}
|
||||
|
||||
1. Go to your Rundeck web interface, and click on the desired job.
|
||||
Click on **Actions**, and select **Edit this Job**.
|
||||
|
||||
1. Go to the **Notifications** tab. Next to the desired event, click
|
||||
**Add Notification**.
|
||||
|
||||
1. Select **Send Webhook** as the Notification Type. Enter the URL
|
||||
generated above. Ensure payload format is **JSON**, and the method is
|
||||
**POST**. Click **Save**.
|
||||
|
||||
{end_tabs}
|
||||
|
||||
{!congrats.md!}
|
||||
|
||||

|
||||
|
||||
### Related documentation
|
||||
|
||||
{!webhooks-url-specification.md!}
|
||||
31
zerver/webhooks/rundeck/fixtures/duration.json
Normal file
31
zerver/webhooks/rundeck/fixtures/duration.json
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"trigger": "avgduration",
|
||||
"status": "running",
|
||||
"executionId": 6,
|
||||
"execution": {
|
||||
"id": 6,
|
||||
"href": "http://localhost:4440/project/welcome-project-community/execution/show/6",
|
||||
"permalink": null,
|
||||
"status": "running",
|
||||
"project": "welcome-project-community",
|
||||
"executionType": "user",
|
||||
"user": "admin",
|
||||
"date-started": {
|
||||
"unixtime": 1680848069313,
|
||||
"date": "2023-04-07T06:14:29Z"
|
||||
},
|
||||
"job": {
|
||||
"id": "a0296d93-4b10-48d7-8b7d-86ad3f603b85",
|
||||
"averageDuration": 2408,
|
||||
"name": "Global Log Filter Usage",
|
||||
"group": "Basic Examples/Basic Workflows",
|
||||
"project": "welcome-project-community",
|
||||
"description": "Global Log Filter basic example.\r\n\r\nGlobal Log Filter allows you to capture information from the whole job. This example shows how to capture env command data and use it later in the next step as [key-value](https://docs.rundeck.com/docs/manual/log-filters/key-value-data.html#key-value-data) data.\r\n\r\nMore information [here](https://docs.rundeck.com/docs/manual/log-filters/#log-filters).",
|
||||
"href": "http://localhost:4440/api/42/job/a0296d93-4b10-48d7-8b7d-86ad3f603b85",
|
||||
"permalink": "http://localhost:4440/project/welcome-project-community/job/show/a0296d93-4b10-48d7-8b7d-86ad3f603b85"
|
||||
},
|
||||
"description": "env ('Using env command we can extract a lot of keys/values :-)') [... 3 steps]",
|
||||
"argstring": null,
|
||||
"serverUUID": "a14bc3e6-75e8-4fe4-a90d-a16dcc976bf6"
|
||||
}
|
||||
}
|
||||
31
zerver/webhooks/rundeck/fixtures/failure.json
Normal file
31
zerver/webhooks/rundeck/fixtures/failure.json
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"trigger": "failure",
|
||||
"status": "failed",
|
||||
"executionId": 7,
|
||||
"execution": {
|
||||
"id": 7,
|
||||
"href": "http://localhost:4440/project/welcome-project-community/execution/show/7",
|
||||
"permalink": null,
|
||||
"status": "failed",
|
||||
"project": "welcome-project-community",
|
||||
"executionType": "user",
|
||||
"user": "admin",
|
||||
"date-started": {
|
||||
"unixtime": 1680848123396,
|
||||
"date": "2023-04-07T06:15:23Z"
|
||||
},
|
||||
"job": {
|
||||
"id": "a0296d93-4b10-48d7-8b7d-86ad3f603b85",
|
||||
"averageDuration": 2659,
|
||||
"name": "Global Log Filter Usage",
|
||||
"group": "Basic Examples/Basic Workflows",
|
||||
"project": "welcome-project-community",
|
||||
"description": "Global Log Filter basic example.\r\n\r\nGlobal Log Filter allows you to capture information from the whole job. This example shows how to capture env command data and use it later in the next step as [key-value](https://docs.rundeck.com/docs/manual/log-filters/key-value-data.html#key-value-data) data.\r\n\r\nMore information [here](https://docs.rundeck.com/docs/manual/log-filters/#log-filters).",
|
||||
"href": "http://localhost:4440/api/42/job/a0296d93-4b10-48d7-8b7d-86ad3f603b85",
|
||||
"permalink": "http://localhost:4440/project/welcome-project-community/job/show/a0296d93-4b10-48d7-8b7d-86ad3f603b85"
|
||||
},
|
||||
"description": "env ('Using env command we can extract a lot of keys/values :-)') [... 4 steps]",
|
||||
"argstring": null,
|
||||
"serverUUID": "a14bc3e6-75e8-4fe4-a90d-a16dcc976bf6"
|
||||
}
|
||||
}
|
||||
23
zerver/webhooks/rundeck/fixtures/scheduled_start.json
Normal file
23
zerver/webhooks/rundeck/fixtures/scheduled_start.json
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"trigger": "start",
|
||||
"status": "scheduled",
|
||||
"executionId": 12,
|
||||
"execution": {
|
||||
"id": 12,
|
||||
"href": "https://rundeck.com/project/myproject/execution/follow/12",
|
||||
"permalink": null,
|
||||
"status": "scheduled",
|
||||
"project": "myproject",
|
||||
"executionType": "user",
|
||||
"user": "guest",
|
||||
"job": {
|
||||
"id": "a0296d93-4b10-48d7-8b7d-86ad3f603b85",
|
||||
"name": "Global Log Filter Usage",
|
||||
"group": "Basic Examples/Basic Workflows",
|
||||
"project": "MyProject",
|
||||
"description": "Global Log Filter basic example. \n\nMore information: https://docs.rundeck.com/docs/manual/log-filters/#log-filters",
|
||||
"href": "https://rundeck.com/api/1/job/a0296d93-4b10-48d7-8b7d-86ad3f603b85",
|
||||
"permalink": "https://rundeck.com/project/myproject/job/show/a0296d93-4b10-48d7-8b7d-86ad3f603b85"
|
||||
}
|
||||
}
|
||||
}
|
||||
31
zerver/webhooks/rundeck/fixtures/start.json
Normal file
31
zerver/webhooks/rundeck/fixtures/start.json
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"trigger": "start",
|
||||
"status": "running",
|
||||
"executionId": 3,
|
||||
"execution": {
|
||||
"id": 3,
|
||||
"href": "http://localhost:4440/project/welcome-project-community/execution/show/3",
|
||||
"permalink": null,
|
||||
"status": "running",
|
||||
"project": "welcome-project-community",
|
||||
"executionType": "user",
|
||||
"user": "admin",
|
||||
"date-started": {
|
||||
"unixtime": 1680847933368,
|
||||
"date": "2023-04-07T06:12:13Z"
|
||||
},
|
||||
"job": {
|
||||
"id": "a0296d93-4b10-48d7-8b7d-86ad3f603b85",
|
||||
"averageDuration": 2354,
|
||||
"name": "Global Log Filter Usage",
|
||||
"group": "Basic Examples/Basic Workflows",
|
||||
"project": "welcome-project-community",
|
||||
"description": "Global Log Filter basic example.\r\n\r\nGlobal Log Filter allows you to capture information from the whole job. This example shows how to capture env command data and use it later in the next step as [key-value](https://docs.rundeck.com/docs/manual/log-filters/key-value-data.html#key-value-data) data.\r\n\r\nMore information [here](https://docs.rundeck.com/docs/manual/log-filters/#log-filters).",
|
||||
"href": "http://localhost:4440/api/42/job/a0296d93-4b10-48d7-8b7d-86ad3f603b85",
|
||||
"permalink": "http://localhost:4440/project/welcome-project-community/job/show/a0296d93-4b10-48d7-8b7d-86ad3f603b85"
|
||||
},
|
||||
"description": "env ('Using env command we can extract a lot of keys/values :-)') [... 2 steps]",
|
||||
"argstring": null,
|
||||
"serverUUID": "a14bc3e6-75e8-4fe4-a90d-a16dcc976bf6"
|
||||
}
|
||||
}
|
||||
31
zerver/webhooks/rundeck/fixtures/success.json
Normal file
31
zerver/webhooks/rundeck/fixtures/success.json
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"trigger": "success",
|
||||
"status": "succeeded",
|
||||
"executionId": 3,
|
||||
"execution": {
|
||||
"id": 3,
|
||||
"href": "http://localhost:4440/project/welcome-project-community/execution/show/3",
|
||||
"permalink": null,
|
||||
"status": "succeeded",
|
||||
"project": "welcome-project-community",
|
||||
"executionType": "user",
|
||||
"user": "admin",
|
||||
"date-started": {
|
||||
"unixtime": 1680847933368,
|
||||
"date": "2023-04-07T06:12:13Z"
|
||||
},
|
||||
"job": {
|
||||
"id": "a0296d93-4b10-48d7-8b7d-86ad3f603b85",
|
||||
"averageDuration": 2354,
|
||||
"name": "Global Log Filter Usage",
|
||||
"group": "Basic Examples/Basic Workflows",
|
||||
"project": "welcome-project-community",
|
||||
"description": "Global Log Filter basic example.\r\n\r\nGlobal Log Filter allows you to capture information from the whole job. This example shows how to capture env command data and use it later in the next step as [key-value](https://docs.rundeck.com/docs/manual/log-filters/key-value-data.html#key-value-data) data.\r\n\r\nMore information [here](https://docs.rundeck.com/docs/manual/log-filters/#log-filters).",
|
||||
"href": "http://localhost:4440/api/42/job/a0296d93-4b10-48d7-8b7d-86ad3f603b85",
|
||||
"permalink": "http://localhost:4440/project/welcome-project-community/job/show/a0296d93-4b10-48d7-8b7d-86ad3f603b85"
|
||||
},
|
||||
"description": "env ('Using env command we can extract a lot of keys/values :-)') [... 2 steps]",
|
||||
"argstring": null,
|
||||
"serverUUID": "a14bc3e6-75e8-4fe4-a90d-a16dcc976bf6"
|
||||
}
|
||||
}
|
||||
55
zerver/webhooks/rundeck/tests.py
Normal file
55
zerver/webhooks/rundeck/tests.py
Normal file
@@ -0,0 +1,55 @@
|
||||
from zerver.lib.test_classes import WebhookTestCase
|
||||
|
||||
|
||||
class RundeckHookTests(WebhookTestCase):
|
||||
TOPIC_NAME = "Global Log Filter Usage"
|
||||
|
||||
def test_start_message(self) -> None:
|
||||
expected_message = "[Global Log Filter Usage](http://localhost:4440/project/welcome-project-community/job/show/a0296d93-4b10-48d7-8b7d-86ad3f603b85) execution [#3](http://localhost:4440/project/welcome-project-community/execution/show/3) for welcome-project-community has started. :running:"
|
||||
|
||||
self.check_webhook(
|
||||
"start",
|
||||
RundeckHookTests.TOPIC_NAME,
|
||||
expected_message,
|
||||
content_type="application/x-www-form-urlencoded",
|
||||
)
|
||||
|
||||
def test_success_message(self) -> None:
|
||||
expected_message = "[Global Log Filter Usage](http://localhost:4440/project/welcome-project-community/job/show/a0296d93-4b10-48d7-8b7d-86ad3f603b85) execution [#3](http://localhost:4440/project/welcome-project-community/execution/show/3) for welcome-project-community has succeeded. :check:"
|
||||
|
||||
self.check_webhook(
|
||||
"success",
|
||||
RundeckHookTests.TOPIC_NAME,
|
||||
expected_message,
|
||||
content_type="application/x-www-form-urlencoded",
|
||||
)
|
||||
|
||||
def test_failure_message(self) -> None:
|
||||
expected_message = "[Global Log Filter Usage](http://localhost:4440/project/welcome-project-community/job/show/a0296d93-4b10-48d7-8b7d-86ad3f603b85) execution [#7](http://localhost:4440/project/welcome-project-community/execution/show/7) for welcome-project-community has failed. :cross_mark:"
|
||||
|
||||
self.check_webhook(
|
||||
"failure",
|
||||
RundeckHookTests.TOPIC_NAME,
|
||||
expected_message,
|
||||
content_type="application/x-www-form-urlencoded",
|
||||
)
|
||||
|
||||
def test_duration_message(self) -> None:
|
||||
expected_message = "[Global Log Filter Usage](http://localhost:4440/project/welcome-project-community/job/show/a0296d93-4b10-48d7-8b7d-86ad3f603b85) execution [#6](http://localhost:4440/project/welcome-project-community/execution/show/6) for welcome-project-community is running long. :time_ticking:"
|
||||
|
||||
self.check_webhook(
|
||||
"duration",
|
||||
RundeckHookTests.TOPIC_NAME,
|
||||
expected_message,
|
||||
content_type="application/x-www-form-urlencoded",
|
||||
)
|
||||
|
||||
def test_scheduled_start_message(self) -> None:
|
||||
expected_message = "[Global Log Filter Usage](https://rundeck.com/project/myproject/job/show/a0296d93-4b10-48d7-8b7d-86ad3f603b85) execution [#12](https://rundeck.com/project/myproject/execution/follow/12) for myproject has started. :running:"
|
||||
|
||||
self.check_webhook(
|
||||
"scheduled_start",
|
||||
RundeckHookTests.TOPIC_NAME,
|
||||
expected_message,
|
||||
content_type="application/x-www-form-urlencoded",
|
||||
)
|
||||
66
zerver/webhooks/rundeck/view.py
Normal file
66
zerver/webhooks/rundeck/view.py
Normal file
@@ -0,0 +1,66 @@
|
||||
from django.http import HttpRequest, HttpResponse
|
||||
|
||||
from zerver.decorator import webhook_view
|
||||
from zerver.lib.response import json_success
|
||||
from zerver.lib.typed_endpoint import JsonBodyPayload, typed_endpoint
|
||||
from zerver.lib.validator import WildValue, check_int, check_string
|
||||
from zerver.lib.webhooks.common import check_send_webhook_message
|
||||
from zerver.models import UserProfile
|
||||
|
||||
RUNDECK_MESSAGE_TEMPLATE = "[{job_name}]({job_link}) execution [#{execution_id}]({execution_link}) for {project_name} {status}. :{emoji}:"
|
||||
RUNDECK_TOPIC_TEMPLATE = "{job_name}"
|
||||
|
||||
|
||||
@webhook_view("Rundeck")
|
||||
@typed_endpoint
|
||||
def api_rundeck_webhook(
|
||||
request: HttpRequest,
|
||||
user_profile: UserProfile,
|
||||
*,
|
||||
payload: JsonBodyPayload[WildValue],
|
||||
) -> HttpResponse:
|
||||
topic_name = get_topic(payload)
|
||||
body = get_body(payload)
|
||||
|
||||
check_send_webhook_message(request, user_profile, topic_name, body)
|
||||
return json_success(request)
|
||||
|
||||
|
||||
def get_topic(payload: WildValue) -> str:
|
||||
return RUNDECK_TOPIC_TEMPLATE.format(
|
||||
job_name=payload["execution"]["job"]["name"].tame(check_string)
|
||||
)
|
||||
|
||||
|
||||
def get_body(payload: WildValue) -> str:
|
||||
message_data = {
|
||||
"job_name": payload["execution"]["job"]["name"].tame(check_string),
|
||||
"job_link": payload["execution"]["job"]["permalink"].tame(check_string),
|
||||
"execution_id": payload["execution"]["id"].tame(check_int),
|
||||
"execution_link": payload["execution"]["href"].tame(check_string),
|
||||
"project_name": payload["execution"]["project"].tame(check_string),
|
||||
"status": payload["execution"]["status"].tame(check_string),
|
||||
}
|
||||
status = payload["execution"]["status"].tame(check_string)
|
||||
|
||||
if status == "failed":
|
||||
message_data["status"] = "has failed"
|
||||
message_data["emoji"] = "cross_mark"
|
||||
|
||||
if status == "succeeded":
|
||||
message_data["status"] = "has succeeded"
|
||||
message_data["emoji"] = "check"
|
||||
|
||||
if status == "running":
|
||||
if payload["trigger"].tame(check_string) == "avgduration":
|
||||
message_data["status"] = "is running long"
|
||||
message_data["emoji"] = "time_ticking"
|
||||
else:
|
||||
message_data["status"] = "has started"
|
||||
message_data["emoji"] = "running"
|
||||
|
||||
if status == "scheduled":
|
||||
message_data["status"] = "has started"
|
||||
message_data["emoji"] = "running"
|
||||
|
||||
return RUNDECK_MESSAGE_TEMPLATE.format(**message_data)
|
||||
Reference in New Issue
Block a user