From bf9cbe30a7b5ee9022d1c6ce981130e195ac7802 Mon Sep 17 00:00:00 2001 From: Johan Nilsson Date: Sat, 7 Sep 2024 16:25:54 +0200 Subject: [PATCH] integrations: Add support for release events to GitLab integration. --- zerver/lib/webhooks/git.py | 6 ++ .../gitlab/fixtures/release_hook__create.json | 69 +++++++++++++++++++ .../gitlab/fixtures/release_hook__delete.json | 69 +++++++++++++++++++ .../gitlab/fixtures/release_hook__update.json | 69 +++++++++++++++++++ zerver/webhooks/gitlab/tests.py | 25 +++++++ zerver/webhooks/gitlab/view.py | 27 ++++++++ 6 files changed, 265 insertions(+) create mode 100644 zerver/webhooks/gitlab/fixtures/release_hook__create.json create mode 100644 zerver/webhooks/gitlab/fixtures/release_hook__delete.json create mode 100644 zerver/webhooks/gitlab/fixtures/release_hook__update.json diff --git a/zerver/lib/webhooks/git.py b/zerver/lib/webhooks/git.py index 2d9c2a5dd4..660719b789 100644 --- a/zerver/lib/webhooks/git.py +++ b/zerver/lib/webhooks/git.py @@ -75,6 +75,12 @@ TAG_WITH_URL_TEMPLATE = "[{tag_name}]({tag_url})" TAG_WITHOUT_URL_TEMPLATE = "{tag_name}" RELEASE_MESSAGE_TEMPLATE = "{user_name} {action} release [{release_name}]({url}) for tag {tagname}." +RELEASE_MESSAGE_TEMPLATE_WITHOUT_USER_NAME = ( + "Release [{release_name}]({url}) for tag {tagname} was {action}." +) +RELEASE_MESSAGE_TEMPLATE_WITHOUT_USER_NAME_WITHOUT_URL = ( + "Release {release_name} for tag {tagname} was {action}." +) def get_assignee_string(assignees: list[dict[str, Any]]) -> str: diff --git a/zerver/webhooks/gitlab/fixtures/release_hook__create.json b/zerver/webhooks/gitlab/fixtures/release_hook__create.json new file mode 100644 index 0000000000..de63ec9bda --- /dev/null +++ b/zerver/webhooks/gitlab/fixtures/release_hook__create.json @@ -0,0 +1,69 @@ +{ + "id": 1, + "created_at": "2020-11-02 12:55:12 UTC", + "description": "## v1.1 (2024-09-06)\n\n- Feature added", + "name": "v1.1", + "released_at": "2020-11-02 12:55:12 UTC", + "tag": "v1.1", + "object_kind": "release", + "project": { + "id": 2, + "name": "release-webhook-example", + "description": "", + "web_url": "https://example.com/gitlab-org/release-webhook-example", + "avatar_url": null, + "git_ssh_url": "ssh://git@example.com/gitlab-org/release-webhook-example.git", + "git_http_url": "https://example.com/gitlab-org/release-webhook-example.git", + "namespace": "Gitlab", + "visibility_level": 0, + "path_with_namespace": "gitlab-org/release-webhook-example", + "default_branch": "master", + "ci_config_path": null, + "homepage": "https://example.com/gitlab-org/release-webhook-example", + "url": "ssh://git@example.com/gitlab-org/release-webhook-example.git", + "ssh_url": "ssh://git@example.com/gitlab-org/release-webhook-example.git", + "http_url": "https://example.com/gitlab-org/release-webhook-example.git" + }, + "url": "https://example.com/gitlab-org/release-webhook-example/-/releases/v1.1", + "action": "create", + "assets": { + "count": 5, + "links": [ + { + "id": 1, + "link_type": "other", + "name": "Changelog", + "url": "https://example.net/changelog" + } + ], + "sources": [ + { + "format": "zip", + "url": "https://example.com/gitlab-org/release-webhook-example/-/archive/v1.1/release-webhook-example-v1.1.zip" + }, + { + "format": "tar.gz", + "url": "https://example.com/gitlab-org/release-webhook-example/-/archive/v1.1/release-webhook-example-v1.1.tar.gz" + }, + { + "format": "tar.bz2", + "url": "https://example.com/gitlab-org/release-webhook-example/-/archive/v1.1/release-webhook-example-v1.1.tar.bz2" + }, + { + "format": "tar", + "url": "https://example.com/gitlab-org/release-webhook-example/-/archive/v1.1/release-webhook-example-v1.1.tar" + } + ] + }, + "commit": { + "id": "ee0a3fb31ac16e11b9dbb596ad16d4af654d08f8", + "message": "Release v1.1", + "title": "Release v1.1", + "timestamp": "2020-10-31T14:58:32+11:00", + "url": "https://example.com/gitlab-org/release-webhook-example/-/commit/ee0a3fb31ac16e11b9dbb596ad16d4af654d08f8", + "author": { + "name": "Example User", + "email": "user@example.com" + } + } +} diff --git a/zerver/webhooks/gitlab/fixtures/release_hook__delete.json b/zerver/webhooks/gitlab/fixtures/release_hook__delete.json new file mode 100644 index 0000000000..97cc3ebf5b --- /dev/null +++ b/zerver/webhooks/gitlab/fixtures/release_hook__delete.json @@ -0,0 +1,69 @@ +{ + "id": 1, + "created_at": "2020-11-02 12:55:12 UTC", + "description": "## v1.1 (2024-09-06)\n\n- Feature added", + "name": "v1.1", + "released_at": "2020-11-02 12:55:12 UTC", + "tag": "v1.1", + "object_kind": "release", + "project": { + "id": 2, + "name": "release-webhook-example", + "description": "", + "web_url": "https://example.com/gitlab-org/release-webhook-example", + "avatar_url": null, + "git_ssh_url": "ssh://git@example.com/gitlab-org/release-webhook-example.git", + "git_http_url": "https://example.com/gitlab-org/release-webhook-example.git", + "namespace": "Gitlab", + "visibility_level": 0, + "path_with_namespace": "gitlab-org/release-webhook-example", + "default_branch": "master", + "ci_config_path": null, + "homepage": "https://example.com/gitlab-org/release-webhook-example", + "url": "ssh://git@example.com/gitlab-org/release-webhook-example.git", + "ssh_url": "ssh://git@example.com/gitlab-org/release-webhook-example.git", + "http_url": "https://example.com/gitlab-org/release-webhook-example.git" + }, + "url": "https://example.com/gitlab-org/release-webhook-example/-/releases/v1.1", + "action": "delete", + "assets": { + "count": 5, + "links": [ + { + "id": 1, + "link_type": "other", + "name": "Changelog", + "url": "https://example.net/changelog" + } + ], + "sources": [ + { + "format": "zip", + "url": "https://example.com/gitlab-org/release-webhook-example/-/archive/v1.1/release-webhook-example-v1.1.zip" + }, + { + "format": "tar.gz", + "url": "https://example.com/gitlab-org/release-webhook-example/-/archive/v1.1/release-webhook-example-v1.1.tar.gz" + }, + { + "format": "tar.bz2", + "url": "https://example.com/gitlab-org/release-webhook-example/-/archive/v1.1/release-webhook-example-v1.1.tar.bz2" + }, + { + "format": "tar", + "url": "https://example.com/gitlab-org/release-webhook-example/-/archive/v1.1/release-webhook-example-v1.1.tar" + } + ] + }, + "commit": { + "id": "ee0a3fb31ac16e11b9dbb596ad16d4af654d08f8", + "message": "Release v1.1", + "title": "Release v1.1", + "timestamp": "2020-10-31T14:58:32+11:00", + "url": "https://example.com/gitlab-org/release-webhook-example/-/commit/ee0a3fb31ac16e11b9dbb596ad16d4af654d08f8", + "author": { + "name": "Example User", + "email": "user@example.com" + } + } +} diff --git a/zerver/webhooks/gitlab/fixtures/release_hook__update.json b/zerver/webhooks/gitlab/fixtures/release_hook__update.json new file mode 100644 index 0000000000..b0b83746a7 --- /dev/null +++ b/zerver/webhooks/gitlab/fixtures/release_hook__update.json @@ -0,0 +1,69 @@ +{ + "id": 1, + "created_at": "2020-11-02 12:55:12 UTC", + "description": "## v1.1 (2024-09-06)\n\n- Feature added", + "name": "v1.1", + "released_at": "2020-11-02 12:55:12 UTC", + "tag": "v1.1", + "object_kind": "release", + "project": { + "id": 2, + "name": "release-webhook-example", + "description": "", + "web_url": "https://example.com/gitlab-org/release-webhook-example", + "avatar_url": null, + "git_ssh_url": "ssh://git@example.com/gitlab-org/release-webhook-example.git", + "git_http_url": "https://example.com/gitlab-org/release-webhook-example.git", + "namespace": "Gitlab", + "visibility_level": 0, + "path_with_namespace": "gitlab-org/release-webhook-example", + "default_branch": "master", + "ci_config_path": null, + "homepage": "https://example.com/gitlab-org/release-webhook-example", + "url": "ssh://git@example.com/gitlab-org/release-webhook-example.git", + "ssh_url": "ssh://git@example.com/gitlab-org/release-webhook-example.git", + "http_url": "https://example.com/gitlab-org/release-webhook-example.git" + }, + "url": "https://example.com/gitlab-org/release-webhook-example/-/releases/v1.1", + "action": "update", + "assets": { + "count": 5, + "links": [ + { + "id": 1, + "link_type": "other", + "name": "Changelog", + "url": "https://example.net/changelog" + } + ], + "sources": [ + { + "format": "zip", + "url": "https://example.com/gitlab-org/release-webhook-example/-/archive/v1.1/release-webhook-example-v1.1.zip" + }, + { + "format": "tar.gz", + "url": "https://example.com/gitlab-org/release-webhook-example/-/archive/v1.1/release-webhook-example-v1.1.tar.gz" + }, + { + "format": "tar.bz2", + "url": "https://example.com/gitlab-org/release-webhook-example/-/archive/v1.1/release-webhook-example-v1.1.tar.bz2" + }, + { + "format": "tar", + "url": "https://example.com/gitlab-org/release-webhook-example/-/archive/v1.1/release-webhook-example-v1.1.tar" + } + ] + }, + "commit": { + "id": "ee0a3fb31ac16e11b9dbb596ad16d4af654d08f8", + "message": "Release v1.1", + "title": "Release v1.1", + "timestamp": "2020-10-31T14:58:32+11:00", + "url": "https://example.com/gitlab-org/release-webhook-example/-/commit/ee0a3fb31ac16e11b9dbb596ad16d4af654d08f8", + "author": { + "name": "Example User", + "email": "user@example.com" + } + } +} diff --git a/zerver/webhooks/gitlab/tests.py b/zerver/webhooks/gitlab/tests.py index 01690e0947..0703541d41 100644 --- a/zerver/webhooks/gitlab/tests.py +++ b/zerver/webhooks/gitlab/tests.py @@ -631,3 +631,28 @@ A trivial change that should probably be ignored. self.check_webhook( "merge_request_hook__merge_request_unapproved", expected_topic_name, expected_message ) + + def test_release_created_event_message(self) -> None: + expected_topic_name = "release-webhook-example" + expected_message = "Release [v1.1](https://example.com/gitlab-org/release-webhook-example/-/releases/v1.1) for tag v1.1 was created.\n~~~ quote\n## v1.1 (2024-09-06)\n\n- Feature added\n~~~" + + self.check_webhook("release_hook__create", expected_topic_name, expected_message) + + def test_release_created_event_message_custom_topic_in_url(self) -> None: + self.url = self.build_webhook_url("topic=Specific%20topic") + expected_topic_name = "Specific topic" + expected_message = "[[release-webhook-example](https://example.com/gitlab-org/release-webhook-example)] Release [v1.1](https://example.com/gitlab-org/release-webhook-example/-/releases/v1.1) for tag v1.1 was created.\n~~~ quote\n## v1.1 (2024-09-06)\n\n- Feature added\n~~~" + + self.check_webhook("release_hook__create", expected_topic_name, expected_message) + + def test_release_update_event_message(self) -> None: + expected_topic_name = "release-webhook-example" + expected_message = "Release [v1.1](https://example.com/gitlab-org/release-webhook-example/-/releases/v1.1) for tag v1.1 was updated.\n~~~ quote\n## v1.1 (2024-09-06)\n\n- Feature added\n~~~" + + self.check_webhook("release_hook__update", expected_topic_name, expected_message) + + def test_release_delete_event_message(self) -> None: + expected_topic_name = "release-webhook-example" + expected_message = "Release v1.1 for tag v1.1 was deleted." + + self.check_webhook("release_hook__delete", expected_topic_name, expected_message) diff --git a/zerver/webhooks/gitlab/view.py b/zerver/webhooks/gitlab/view.py index 45123030b6..3d1cab6c9c 100644 --- a/zerver/webhooks/gitlab/view.py +++ b/zerver/webhooks/gitlab/view.py @@ -16,7 +16,10 @@ from zerver.lib.webhooks.common import ( validate_extract_webhook_http_header, ) from zerver.lib.webhooks.git import ( + CONTENT_MESSAGE_TEMPLATE, EMPTY_SHA, + RELEASE_MESSAGE_TEMPLATE_WITHOUT_USER_NAME, + RELEASE_MESSAGE_TEMPLATE_WITHOUT_USER_NAME_WITHOUT_URL, TOPIC_WITH_PR_OR_ISSUE_INFO_TEMPLATE, get_commits_comment_action_message, get_issue_event_message, @@ -342,6 +345,29 @@ def get_pipeline_event_body(payload: WildValue, include_title: bool) -> str: ) +def get_release_event_body(payload: WildValue, include_title: bool) -> str: + action = payload["action"].tame(check_string) + name = payload["name"].tame(check_string) + tag = payload["tag"].tame(check_string) + message_action = f"{action}d" + + if action == "delete": + body = RELEASE_MESSAGE_TEMPLATE_WITHOUT_USER_NAME_WITHOUT_URL.format( + release_name=name, tagname=tag, action=message_action + ) + else: + url = payload["url"].tame(check_string) + body = RELEASE_MESSAGE_TEMPLATE_WITHOUT_USER_NAME.format( + release_name=name, url=url, tagname=tag, action=message_action + ) + + if "description" in payload: + description = payload["description"].tame(check_string) + body += CONTENT_MESSAGE_TEMPLATE.format(message=description) + + return body + + def get_repo_name(payload: WildValue) -> str: if "project" in payload: return payload["project"]["name"].tame(check_string) @@ -411,6 +437,7 @@ EVENT_FUNCTION_MAPPER: dict[str, EventFunction] = { "Job Hook": get_build_hook_event_body, "Build Hook": get_build_hook_event_body, "Pipeline Hook": get_pipeline_event_body, + "Release Hook": get_release_event_body, } ALL_EVENT_TYPES = list(EVENT_FUNCTION_MAPPER.keys())