diff --git a/zerver/webhooks/gitlab/fixtures/deployment_hook__canceled.json b/zerver/webhooks/gitlab/fixtures/deployment_hook__canceled.json new file mode 100644 index 0000000000..cb2694a5b4 --- /dev/null +++ b/zerver/webhooks/gitlab/fixtures/deployment_hook__canceled.json @@ -0,0 +1,42 @@ +{ + "object_kind": "deployment", + "status": "canceled", + "status_changed_at": "2025-05-02 12:36:52 +0000", + "deployment_id": 988610373, + "deployable_id": 9905830127, + "deployable_url": "https://gitlab.com/vedant8600317/test/-/jobs/9905830127", + "environment": "production", + "environment_tier": "production", + "environment_slug": "production", + "environment_external_url": null, + "project": { + "id": 69310893, + "name": "test", + "description": null, + "web_url": "https://gitlab.com/vedant8600317/test", + "avatar_url": null, + "git_ssh_url": "git@gitlab.com:vedant8600317/test.git", + "git_http_url": "https://gitlab.com/vedant8600317/test.git", + "namespace": "vedant", + "visibility_level": 0, + "path_with_namespace": "vedant8600317/test", + "default_branch": "master", + "ci_config_path": "", + "homepage": "https://gitlab.com/vedant8600317/test", + "url": "git@gitlab.com:vedant8600317/test.git", + "ssh_url": "git@gitlab.com:vedant8600317/test.git", + "http_url": "https://gitlab.com/vedant8600317/test.git" + }, + "short_sha": "c3cf29e8", + "user": { + "id": 27470334, + "name": "Vedant Joshi", + "username": "theofficialvedantjoshi", + "avatar_url": "https://secure.gravatar.com/avatar/0d29c5c241fe093697c078fbb8abc26b93d4ebbd1609dbbd3835e6b5602fea38?s=80&d=identicon", + "email": "[REDACTED]" + }, + "user_url": "https://gitlab.com/theofficialvedantjoshi", + "commit_url": "https://gitlab.com/vedant8600317/test/-/commit/c3cf29e88c1b0a8a60df37f4687dd5060955d2ae", + "commit_title": "Update .gitlab-ci.yml file", + "ref": "master" +} diff --git a/zerver/webhooks/gitlab/fixtures/deployment_hook__failed.json b/zerver/webhooks/gitlab/fixtures/deployment_hook__failed.json new file mode 100644 index 0000000000..9991c25c7d --- /dev/null +++ b/zerver/webhooks/gitlab/fixtures/deployment_hook__failed.json @@ -0,0 +1,42 @@ +{ + "object_kind": "deployment", + "status": "failed", + "status_changed_at": "2025-05-02 12:30:19 +0000", + "deployment_id": 988604916, + "deployable_id": 9905759933, + "deployable_url": "https://gitlab.com/vedant8600317/test/-/jobs/9905759933", + "environment": "production", + "environment_tier": "production", + "environment_slug": "production", + "environment_external_url": null, + "project": { + "id": 69310893, + "name": "test", + "description": null, + "web_url": "https://gitlab.com/vedant8600317/test", + "avatar_url": null, + "git_ssh_url": "git@gitlab.com:vedant8600317/test.git", + "git_http_url": "https://gitlab.com/vedant8600317/test.git", + "namespace": "vedant", + "visibility_level": 0, + "path_with_namespace": "vedant8600317/test", + "default_branch": "master", + "ci_config_path": "", + "homepage": "https://gitlab.com/vedant8600317/test", + "url": "git@gitlab.com:vedant8600317/test.git", + "ssh_url": "git@gitlab.com:vedant8600317/test.git", + "http_url": "https://gitlab.com/vedant8600317/test.git" + }, + "short_sha": "846d8de0", + "user": { + "id": 27470334, + "name": "Vedant Joshi", + "username": "theofficialvedantjoshi", + "avatar_url": "https://secure.gravatar.com/avatar/0d29c5c241fe093697c078fbb8abc26b93d4ebbd1609dbbd3835e6b5602fea38?s=80&d=identicon", + "email": "[REDACTED]" + }, + "user_url": "https://gitlab.com/theofficialvedantjoshi", + "commit_url": "https://gitlab.com/vedant8600317/test/-/commit/846d8de0b7b3d694954249d2fd5d87fbe8c84e4c", + "commit_title": "Update .gitlab-ci.yml file", + "ref": "master" +} diff --git a/zerver/webhooks/gitlab/fixtures/deployment_hook__running.json b/zerver/webhooks/gitlab/fixtures/deployment_hook__running.json new file mode 100644 index 0000000000..b3b298873d --- /dev/null +++ b/zerver/webhooks/gitlab/fixtures/deployment_hook__running.json @@ -0,0 +1,42 @@ +{ + "object_kind": "deployment", + "status": "running", + "status_changed_at": "2025-05-02 11:54:46 +0000", + "deployment_id": 988572802, + "deployable_id": 9905389091, + "deployable_url": "https://gitlab.com/vedant8600317/test/-/jobs/9905389091", + "environment": "production", + "environment_tier": "production", + "environment_slug": "production", + "environment_external_url": null, + "project": { + "id": 69310893, + "name": "test", + "description": null, + "web_url": "https://gitlab.com/vedant8600317/test", + "avatar_url": null, + "git_ssh_url": "git@gitlab.com:vedant8600317/test.git", + "git_http_url": "https://gitlab.com/vedant8600317/test.git", + "namespace": "vedant", + "visibility_level": 0, + "path_with_namespace": "vedant8600317/test", + "default_branch": "master", + "ci_config_path": "", + "homepage": "https://gitlab.com/vedant8600317/test", + "url": "git@gitlab.com:vedant8600317/test.git", + "ssh_url": "git@gitlab.com:vedant8600317/test.git", + "http_url": "https://gitlab.com/vedant8600317/test.git" + }, + "short_sha": "58793660", + "user": { + "id": 27470334, + "name": "Vedant Joshi", + "username": "theofficialvedantjoshi", + "avatar_url": "https://secure.gravatar.com/avatar/0d29c5c241fe093697c078fbb8abc26b93d4ebbd1609dbbd3835e6b5602fea38?s=80&d=identicon", + "email": "[REDACTED]" + }, + "user_url": "https://gitlab.com/theofficialvedantjoshi", + "commit_url": "https://gitlab.com/vedant8600317/test/-/commit/58793660b22d6ceacbdc23b28a0562bca339702c", + "commit_title": "Update .gitlab-ci.yml file", + "ref": "master" +} diff --git a/zerver/webhooks/gitlab/fixtures/deployment_hook__success.json b/zerver/webhooks/gitlab/fixtures/deployment_hook__success.json new file mode 100644 index 0000000000..42ce9d4605 --- /dev/null +++ b/zerver/webhooks/gitlab/fixtures/deployment_hook__success.json @@ -0,0 +1,42 @@ +{ + "object_kind": "deployment", + "status": "success", + "status_changed_at": "2025-05-02 11:55:16 +0000", + "deployment_id": 988572802, + "deployable_id": 9905389091, + "deployable_url": "https://gitlab.com/vedant8600317/test/-/jobs/9905389091", + "environment": "production", + "environment_tier": "production", + "environment_slug": "production", + "environment_external_url": null, + "project": { + "id": 69310893, + "name": "test", + "description": null, + "web_url": "https://gitlab.com/vedant8600317/test", + "avatar_url": null, + "git_ssh_url": "git@gitlab.com:vedant8600317/test.git", + "git_http_url": "https://gitlab.com/vedant8600317/test.git", + "namespace": "vedant", + "visibility_level": 0, + "path_with_namespace": "vedant8600317/test", + "default_branch": "master", + "ci_config_path": "", + "homepage": "https://gitlab.com/vedant8600317/test", + "url": "git@gitlab.com:vedant8600317/test.git", + "ssh_url": "git@gitlab.com:vedant8600317/test.git", + "http_url": "https://gitlab.com/vedant8600317/test.git" + }, + "short_sha": "58793660", + "user": { + "id": 27470334, + "name": "Vedant Joshi", + "username": "theofficialvedantjoshi", + "avatar_url": "https://secure.gravatar.com/avatar/0d29c5c241fe093697c078fbb8abc26b93d4ebbd1609dbbd3835e6b5602fea38?s=80&d=identicon", + "email": "[REDACTED]" + }, + "user_url": "https://gitlab.com/theofficialvedantjoshi", + "commit_url": "https://gitlab.com/vedant8600317/test/-/commit/58793660b22d6ceacbdc23b28a0562bca339702c", + "commit_title": "Update .gitlab-ci.yml file", + "ref": "master" +} diff --git a/zerver/webhooks/gitlab/tests.py b/zerver/webhooks/gitlab/tests.py index d2f15999db..94bd9a6312 100644 --- a/zerver/webhooks/gitlab/tests.py +++ b/zerver/webhooks/gitlab/tests.py @@ -713,3 +713,49 @@ A trivial change that should probably be ignored. self.check_webhook( "resource_access_token_hook__group_expiry", expected_topic_name, expected_message ) + + def test_deployment_started_event_message(self) -> None: + expected_topic_name = "test / production" + expected_message = "[Vedant Joshi](https://gitlab.com/theofficialvedantjoshi) started a new [deployment](https://gitlab.com/vedant8600317/test/-/jobs/9905389091):\n> [5879366](https://gitlab.com/vedant8600317/test/-/commit/58793660b22d6ceacbdc23b28a0562bca339702c) Update .gitlab-ci.yml file" + + self.check_webhook( + "deployment_hook__running", + expected_topic_name, + expected_message, + HTTP_X_GITLAB_EVENT="Deployment Hook", + ) + + def test_deployment_succeeded_event_message(self) -> None: + expected_topic_name = "test / production" + expected_message = "The [deployment](https://gitlab.com/vedant8600317/test/-/jobs/9905389091) was successful." + + self.check_webhook( + "deployment_hook__success", + expected_topic_name, + expected_message, + HTTP_X_GITLAB_EVENT="Deployment Hook", + ) + + def test_deployment_failed_event_message(self) -> None: + expected_topic_name = "test / production" + expected_message = ( + "The [deployment](https://gitlab.com/vedant8600317/test/-/jobs/9905759933) failed." + ) + + self.check_webhook( + "deployment_hook__failed", + expected_topic_name, + expected_message, + HTTP_X_GITLAB_EVENT="Deployment Hook", + ) + + def test_deployment_canceled_event_message(self) -> None: + expected_topic_name = "test / production" + expected_message = "The [deployment](https://gitlab.com/vedant8600317/test/-/jobs/9905830127) was canceled." + + self.check_webhook( + "deployment_hook__canceled", + expected_topic_name, + expected_message, + HTTP_X_GITLAB_EVENT="Deployment Hook", + ) diff --git a/zerver/webhooks/gitlab/view.py b/zerver/webhooks/gitlab/view.py index 0f6750801e..605e384c03 100644 --- a/zerver/webhooks/gitlab/view.py +++ b/zerver/webhooks/gitlab/view.py @@ -455,6 +455,29 @@ def get_resource_access_token_expiry_event_body(payload: WildValue, include_titl ) +def get_deployment_event_body(payload: WildValue, include_title: bool) -> str: + user_text = ( + f"[{payload['user']['name'].tame(check_string)}]({payload['user_url'].tame(check_string)})" + ) + + deployment_status = payload["status"].tame(check_string) + deployable_url = payload.get("deployable_url", "").tame(check_string) + deployment_text = f"[deployment]({deployable_url})" if deployable_url else "deployment" + + commit_title = payload["commit_title"].tame(check_string) + commit_url = payload["commit_url"].tame(check_string) + commit_sha = commit_url.split("/")[-1][:7] + + deployment_event_body_map = { + "running": f"{user_text} started a new {deployment_text}:\n> [{commit_sha}]({commit_url}) {commit_title}", + "success": f"The {deployment_text} was successful.", + "failed": f"The {deployment_text} failed.", + "canceled": f"The {deployment_text} was canceled.", + } + + return deployment_event_body_map[deployment_status] + + def get_repo_name(payload: WildValue) -> str: if "project" in payload: return payload["project"]["name"].tame(check_string) @@ -544,6 +567,7 @@ EVENT_FUNCTION_MAPPER: dict[str, EventFunction] = { "Release Hook": get_release_event_body, "Feature Flag Hook": get_feature_flag_event_body, "Resource Access Token Hook": get_resource_access_token_expiry_event_body, + "Deployment Hook": get_deployment_event_body, } ALL_EVENT_TYPES = list(EVENT_FUNCTION_MAPPER.keys()) @@ -655,6 +679,11 @@ def get_topic_based_on_event(event: str, payload: WildValue, use_merge_request_t elif event == "Resource Access Token Hook" and payload.get("group"): return payload["group"]["group_name"].tame(check_string) + elif event == "Deployment Hook": + return "{} / {}".format( + get_repo_name(payload), + payload["environment"].tame(check_string), + ) return get_repo_name(payload)