From 5224df10061dc8c6b7cdb1e906ff4c0b425ce94d Mon Sep 17 00:00:00 2001 From: Meni Yakove Date: Tue, 25 Feb 2025 13:37:07 +0200 Subject: [PATCH 1/3] feat: add conventional-title check to check pr title --- example.config.yaml | 2 ++ webhook_server_container/config/schema.yaml | 2 ++ webhook_server_container/libs/github_api.py | 39 +++++++++++++++++++++ webhook_server_container/utils/constants.py | 2 +- 4 files changed, 44 insertions(+), 1 deletion(-) diff --git a/example.config.yaml b/example.config.yaml index b52426ab..0364ee56 100644 --- a/example.config.yaml +++ b/example.config.yaml @@ -92,3 +92,5 @@ repositories: epic: # Optional user-mapping: : # if github user is not the same as jira + + conventional-title: "ci,docs,feat,fix,refactor,test,release" # Check PR title start with any of these words + : diff --git a/webhook_server_container/config/schema.yaml b/webhook_server_container/config/schema.yaml index 8fd0c899..b27e042f 100644 --- a/webhook_server_container/config/schema.yaml +++ b/webhook_server_container/config/schema.yaml @@ -148,3 +148,5 @@ properties: jira-tracking: type: boolean default: true + + conventional-title: string diff --git a/webhook_server_container/libs/github_api.py b/webhook_server_container/libs/github_api.py index f0970fc1..7c43cc22 100644 --- a/webhook_server_container/libs/github_api.py +++ b/webhook_server_container/libs/github_api.py @@ -44,6 +44,7 @@ COMMAND_CHERRY_PICK_STR, COMMAND_RETEST_STR, COMMENTED_BY_LABEL_PREFIX, + CONVENTIONAL_TITLE_STR, DELETE_STR, DYNAMIC_LABELS_DICT, FAILURE_STR, @@ -427,6 +428,9 @@ def _repo_data_from_config(self) -> None: key="can-be-merged-required-labels", return_on_none=[], ) + self.conventional_title: str = get_value_from_dicts( + primary_dict=repo_data, secondary_dict=config_data, key="conventional-title" + ) def _get_pull_request(self, number: Optional[int] = None) -> PullRequest: if number: @@ -743,6 +747,18 @@ def set_python_module_install_success(self, output: Dict[str, Any]) -> None: def set_python_module_install_failure(self, output: Dict[str, Any]) -> None: return self.set_check_run_status(check_run=PYTHON_MODULE_INSTALL_STR, conclusion=FAILURE_STR, output=output) + def set_conventional_title_queued(self) -> None: + return self.set_check_run_status(check_run=CONVENTIONAL_TITLE_STR, status=QUEUED_STR) + + def set_conventional_title_in_progress(self) -> None: + return self.set_check_run_status(check_run=CONVENTIONAL_TITLE_STR, status=IN_PROGRESS_STR) + + def set_conventional_title_success(self, output: Dict[str, Any]) -> None: + return self.set_check_run_status(check_run=CONVENTIONAL_TITLE_STR, conclusion=SUCCESS_STR, output=output) + + def set_conventional_title_failure(self, output: Dict[str, Any]) -> None: + return self.set_check_run_status(check_run=CONVENTIONAL_TITLE_STR, conclusion=FAILURE_STR, output=output) + def set_cherry_pick_in_progress(self) -> None: return self.set_check_run_status(check_run=CHERRY_PICKED_LABEL_PREFIX, status=IN_PROGRESS_STR) @@ -849,6 +865,8 @@ def process_pull_request_webhook_data(self) -> None: pull_request_data: Dict[str, Any] = self.hook_data["pull_request"] self.parent_committer = pull_request_data["user"]["login"] self.pull_request_branch = pull_request_data["base"]["ref"] + self.set_conventional_title_queued() + self.conventional_title_check() if hook_action == "edited": self.set_wip_label_based_on_title() @@ -1706,6 +1724,9 @@ def get_all_required_status_checks(self) -> List[str]: if self.pypi: all_required_status_checks.append(PYTHON_MODULE_INSTALL_STR) + if self.conventional_title: + all_required_status_checks.append(CONVENTIONAL_TITLE_STR) + _all_required_status_checks = branch_required_status_checks + all_required_status_checks self.logger.debug(f"{self.log_prefix} All required status checks: {_all_required_status_checks}") return _all_required_status_checks @@ -2228,3 +2249,21 @@ def _add_reviewer_by_user_comment(self, reviewer: str) -> None: _err = f"not adding reviewer {reviewer} by user comment, {reviewer} is not part of contributers" self.logger.debug(f"{self.log_prefix} {_err}") self.pull_request.create_issue_comment(_err) + + def conventional_title_check(self) -> None: + if self.conventional_title: + output: Dict[str, str] = { + "title": "Conventional Title", + "summary": "", + "text": "", + } + self.set_conventional_title_in_progress() + allowed_names = self.conventional_title.split(",") + title = self.pull_request.title + if any([title.startswith(_name) for _name in allowed_names]): + self.set_conventional_title_success(output=output) + else: + output["summary"] = "Failed" + output["text"] = f"pull_request title must starts with allowed title: {', '.join(allowed_names)}" + + self.set_conventional_title_failure(output=output) diff --git a/webhook_server_container/utils/constants.py b/webhook_server_container/utils/constants.py index b9a89715..ac8e6713 100644 --- a/webhook_server_container/utils/constants.py +++ b/webhook_server_container/utils/constants.py @@ -1,6 +1,5 @@ from typing import Dict - OTHER_MAIN_BRANCH: str = "master" TOX_STR: str = "tox" PRE_COMMIT_STR: str = "pre-commit" @@ -14,6 +13,7 @@ CAN_BE_MERGED_STR: str = "can-be-merged" BUILD_CONTAINER_STR: str = "build-container" PYTHON_MODULE_INSTALL_STR: str = "python-module-install" +CONVENTIONAL_TITLE_STR: str = "conventional-title" WIP_STR: str = "wip" LGTM_STR: str = "lgtm" CHERRY_PICK_LABEL_PREFIX: str = "cherry-pick-" From 90ae1eeff2462e89c983b0b2cf85098b0982e76a Mon Sep 17 00:00:00 2001 From: Meni Yakove Date: Tue, 25 Feb 2025 13:39:23 +0200 Subject: [PATCH 2/3] fix: error output when check fail --- webhook_server_container/libs/github_api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webhook_server_container/libs/github_api.py b/webhook_server_container/libs/github_api.py index 7c43cc22..157ac1a3 100644 --- a/webhook_server_container/libs/github_api.py +++ b/webhook_server_container/libs/github_api.py @@ -2264,6 +2264,6 @@ def conventional_title_check(self) -> None: self.set_conventional_title_success(output=output) else: output["summary"] = "Failed" - output["text"] = f"pull_request title must starts with allowed title: {', '.join(allowed_names)}" + output["text"] = f"Pull request title must starts with allowed title: {', '.join(allowed_names)}" self.set_conventional_title_failure(output=output) From a3b102a640f43488e503ccf03d6d3a2f05eade5b Mon Sep 17 00:00:00 2001 From: Meni Yakove Date: Tue, 25 Feb 2025 14:04:43 +0200 Subject: [PATCH 3/3] fix: title start with :, error specify the allowed names with `:` --- webhook_server_container/libs/github_api.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/webhook_server_container/libs/github_api.py b/webhook_server_container/libs/github_api.py index 157ac1a3..a90ee0fe 100644 --- a/webhook_server_container/libs/github_api.py +++ b/webhook_server_container/libs/github_api.py @@ -2260,10 +2260,10 @@ def conventional_title_check(self) -> None: self.set_conventional_title_in_progress() allowed_names = self.conventional_title.split(",") title = self.pull_request.title - if any([title.startswith(_name) for _name in allowed_names]): + if any([title.startswith(f"{_name}:") for _name in allowed_names]): self.set_conventional_title_success(output=output) else: output["summary"] = "Failed" - output["text"] = f"Pull request title must starts with allowed title: {', '.join(allowed_names)}" + output["text"] = f"Pull request title must starts with allowed title: {': ,'.join(allowed_names)}" self.set_conventional_title_failure(output=output)