diff --git a/oar/cli/cmd_drop_bugs.py b/oar/cli/cmd_drop_bugs.py index 6cf666189ae7..f72a1417e4bc 100644 --- a/oar/cli/cmd_drop_bugs.py +++ b/oar/cli/cmd_drop_bugs.py @@ -6,6 +6,7 @@ from oar.core.notification import NotificationManager from oar.core.operators import BugOperator from oar.core.worksheet import WorksheetManager +from oar.core.shipment import GitLabServer logger = logging.getLogger(__name__) @@ -40,6 +41,19 @@ def drop_bugs(ctx): logger.info("updating test report") report.update_bug_list(operator.get_jira_issues(), dropped_bugs) nm.share_dropped_bugs(dropped_bugs) + # Get drop-bugs MR to notify ART team + try: + gl = GitLabServer(cs.get_gitlab_url(), cs.get_gitlab_token()) + mr_title = f"{cs.release} drop bugs" + # Try to scope to shipment project when available + project_name = operator._sd.get_mr().project_name if hasattr(operator, '_sd') and operator._sd.get_mr() else None + mr = gl.get_mr_by_title(mr_title, project_name) + if mr: + nm.share_drop_bugs_mr_for_approval(mr.get_web_url()) + else: + logger.warning("drop-bugs MR url not found by title; skipping ART notification") + except Exception as e: + logger.warning("Failed to locate MR url for drop-bugs; skipping ART notification: %s", e) if len(approved_doc_ads): for ad in approved_doc_ads: ad.refresh() diff --git a/oar/core/notification.py b/oar/core/notification.py index d5e9ba5f0dd6..afab73face62 100644 --- a/oar/core/notification.py +++ b/oar/core/notification.py @@ -45,13 +45,6 @@ def share_new_report(self, report: TestReport): NotificationException: error when share this info """ try: - # Send email - # mail_subject = self.cs.release + " z-stream errata test status" - # mail_content = self.mh.get_mail_content_for_new_report(report) - # self.mc.send_email( - # self.cs.get_email_contact("qe"), mail_subject, mail_content - # ) - # Send slack message slack_msg = self.mh.get_slack_message_for_new_report(report) self.sc.post_message( self.cs.get_slack_channel_from_contact("qe-release"), slack_msg @@ -76,7 +69,6 @@ def share_ownership_change_result( """ try: - # Send slack message only slack_msg = self.mh.get_slack_message_for_ownership_change( updated_ads, abnormal_ads, updated_subtasks, new_owner ) @@ -153,7 +145,7 @@ def share_new_cve_tracker_bugs(self, cve_tracker_bugs): cve_tracker_bugs) if len(slack_msg): self.sc.post_message( - self.cs.get_slack_channel_from_contact("art"), slack_msg + self._get_channel("art"), slack_msg ) except Exception as e: raise NotificationException( @@ -195,13 +187,12 @@ def share_dropped_bugs(self, dropped_bugs): slack_msg = self.mh.get_slack_message_for_dropped_bugs(dropped_bugs) if len(slack_msg): self.sc.post_message( - self.cs.get_slack_channel_from_contact( + self._get_channel( "qe-release"), slack_msg ) except Exception as e: raise NotificationException( - "share dropped bugs failed" - ) from e + "share dropped bugs failed") from e def share_dropped_and_high_severity_bugs(self, dropped_bugs, high_severity_bugs): @@ -221,13 +212,12 @@ def share_dropped_and_high_severity_bugs(self, dropped_bugs, high_severity_bugs) ) if len(slack_msg): self.sc.post_message( - self.cs.get_slack_channel_from_contact( + self._get_channel( "qe-release"), slack_msg ) except Exception as e: raise NotificationException( - "share dropped and high severity bugs failed" - ) from e + "share dropped and high severity bugs failed") from e def share_doc_prodsec_approval_result(self, doc_appr, prodsec_appr): """ @@ -239,7 +229,7 @@ def share_doc_prodsec_approval_result(self, doc_appr, prodsec_appr): ) if len(slack_msg): self.sc.post_message( - self.cs.get_slack_channel_from_contact( + self._get_channel( "approver"), slack_msg ) except Exception as e: @@ -325,6 +315,24 @@ def share_shipment_mr_and_ad_info(self, mr, updated_ads, abnormal_ads, updated_s except Exception as e: raise NotificationException("share shipment MR and AD info failed") from e + def share_drop_bugs_mr_for_approval(self, mr_url: str): + """ + Notify ART forum channel to approve the drop-bugs merge request + + Args: + mr_url (str): URL of the drop-bugs merge request + + Raises: + NotificationException: error when posting message + """ + try: + slack_msg = f"ART team, please review and approve the drop-bugs MR: {mr_url}" + # Use forum channel mapping from config + channel = self.cs.get_slack_channel_from_contact("qe-forum") + self.sc.post_message(channel, slack_msg) + except Exception as e: + raise NotificationException("share drop-bugs MR for approval failed") from e + def share_unverified_cve_issues_to_managers(self, unverified_cve_issues): """ Share unverified CVE issues to managers of QA contacts @@ -340,7 +348,7 @@ def share_unverified_cve_issues_to_managers(self, unverified_cve_issues): unverified_cve_issues) if len(slack_msg): self.sc.post_message( - self.cs.get_slack_channel_from_contact( + self._get_channel( "qe-forum"), slack_msg ) except Exception as e: diff --git a/oar/core/shipment.py b/oar/core/shipment.py index b196244d3694..b45d633e22d0 100644 --- a/oar/core/shipment.py +++ b/oar/core/shipment.py @@ -980,17 +980,18 @@ def drop_bugs(self) -> list[str]: # need to check if MR with above title exists or not gl = GitLabServer(self._cs.get_gitlab_url(), self._cs.get_gitlab_token()) gh = GitHelper() - mr = gl.get_mr_by_title(mr_title, self._mr.project_name) + # Look up an existing drop-bugs MR by title in the same project as the shipment MR + drop_bugs_mr = gl.get_mr_by_title(mr_title, self._mr.project_name) # if mr already exists, don't need to create new mr timestamp = datetime.now().strftime("%Y%m%d%H%M%S") repo_dir = "" branch = f"drop-bugs-for-{self._cs.release}-{timestamp}" - if mr: + if drop_bugs_mr: # get source project info from existing mr metadata # check out the branch from source project - source_project = mr.gl.projects.get(mr.mr.source_project_id) - repo_dir = gh.checkout_repo(source_project.http_url_to_repo, mr.get_source_branch()) + source_project = drop_bugs_mr.gl.projects.get(drop_bugs_mr.mr.source_project_id) + repo_dir = gh.checkout_repo(source_project.http_url_to_repo, drop_bugs_mr.get_source_branch()) # configure credential for remote origin, just need to update this branch gh.configure_remotes("origin", f"https://group_143087_bot_e4ed5153eb7e7dfa7eb3d7901a95a6a7:{self._cs.get_gitlab_token()}@gitlab.cee.redhat.com/rioliu/ocp-shipment-data.git") else: @@ -1042,7 +1043,7 @@ def drop_bugs(self) -> list[str]: return [] - if mr: + if drop_bugs_mr: gh.push_changes() else: # push the local change to forked repo diff --git a/tests/test_notification.py b/tests/test_notification.py index af13b07ce83f..b7ad3ea5a4e7 100644 --- a/tests/test_notification.py +++ b/tests/test_notification.py @@ -14,7 +14,7 @@ class TestNotificationManager(unittest.TestCase): def setUp(self): - self.cs = ConfigStore("4.13.6") + self.cs = ConfigStore("4.19.14") self.nm = NotificationManager(self.cs) @unittest.skip @@ -174,3 +174,27 @@ def test_share_unverified_cve_issues_to_managers_error(self): self.nm.share_unverified_cve_issues_to_managers([test_issue]) self.nm.sc.post_message.assert_called_once() + + def test_share_drop_bugs_mr_for_approval_success(self): + """Ensure MR approval request is posted to forum channel with URL""" + mr_url = "https://gitlab.example.com/mygroup/ocp-shipment-data/-/merge_requests/136" + # Mock channel mapping and Slack posting + self.nm.cs.get_slack_channel_from_contact = unittest.mock.Mock(return_value="#forum-ocp-release") + self.nm.sc.post_message = unittest.mock.Mock() + + self.nm.share_drop_bugs_mr_for_approval(mr_url) + + # Validate channel and message contents + self.nm.sc.post_message.assert_called_once() + args, kwargs = self.nm.sc.post_message.call_args + self.assertEqual(args[0], "#forum-ocp-release") + self.assertIn(mr_url, args[1]) + + def test_share_drop_bugs_mr_for_approval_error(self): + """Ensure NotificationException is raised when Slack post fails""" + mr_url = "https://gitlab.example.com/mygroup/ocp-shipment-data/-/merge_requests/999" + self.nm.cs.get_slack_channel_from_contact = unittest.mock.Mock(return_value="#forum-ocp-release") + self.nm.sc.post_message = unittest.mock.Mock(side_effect=Exception("Slack failure")) + + with self.assertRaises(NotificationException): + self.nm.share_drop_bugs_mr_for_approval(mr_url)