11import os
22import re
33from functools import cache
4+ from typing import Any
45
5- from jira import JIRA
6+ from jira import JIRA , JIRAError
67from kubernetes .dynamic import DynamicClient
78from ocp_resources .cluster_service_version import ClusterServiceVersion
89from ocp_resources .exceptions import MissingResourceError
910from packaging .version import Version
1011from pytest_testconfig import config as py_config
12+ from requests .exceptions import ConnectionError as RequestsConnectionError
1113from simple_logger .logger import get_logger
14+ from urllib3 .exceptions import NewConnectionError
1215
1316LOGGER = get_logger (name = __name__ )
1417
18+ JIRA_CLOSED_STATUSES = ("closed" , "resolved" , "testing" )
19+
1520
1621@cache
1722def get_jira_connection () -> JIRA :
@@ -28,6 +33,20 @@ def get_jira_connection() -> JIRA:
2833 )
2934
3035
36+ @cache
37+ def get_jira_issue_fields (jira_id : str ) -> Any :
38+ """
39+ Get Jira issue fields (status and fixVersions).
40+
41+ Args:
42+ jira_id: Jira issue id (e.g. "RHOAIENG-52129").
43+
44+ Returns:
45+ Jira issue fields object with status and fixVersions.
46+ """
47+ return get_jira_connection ().issue (id = jira_id , fields = "status, fixVersions" ).fields
48+
49+
3150def is_jira_open (jira_id : str , admin_client : DynamicClient ) -> bool :
3251 """
3352 Check if Jira issue is open.
@@ -40,15 +59,11 @@ def is_jira_open(jira_id: str, admin_client: DynamicClient) -> bool:
4059 bool: True if Jira issue is open.
4160
4261 """
43- jira_fields = get_jira_connection ().issue (id = jira_id , fields = "status, fixVersions" ).fields
44-
45- jira_status = jira_fields .status .name .lower ()
46-
47- if jira_status not in ("testing" , "resolved" , "closed" ):
48- LOGGER .info (f"Jira { jira_id } : status is { jira_status } " )
62+ if is_jira_issue_open (jira_id = jira_id ):
4963 return True
5064
5165 else :
66+ jira_fields = get_jira_issue_fields (jira_id = jira_id )
5267 # Check if the operator version in ClusterServiceVersion is greater than the jira fix version
5368 jira_fix_versions : list [Version ] = [
5469 Version (_fix_version .group ())
@@ -57,7 +72,7 @@ def is_jira_open(jira_id: str, admin_client: DynamicClient) -> bool:
5772 ]
5873
5974 if not jira_fix_versions :
60- raise ValueError (f"Jira { jira_id } : status is { jira_status } but does not have fix version(s)" )
75+ raise ValueError (f"Jira { jira_id } : closed/resolved but does not have fix version(s)" )
6176
6277 operator_version : str = ""
6378 for csv in ClusterServiceVersion .get (client = admin_client , namespace = py_config ["applications_namespace" ]):
@@ -71,9 +86,31 @@ def is_jira_open(jira_id: str, admin_client: DynamicClient) -> bool:
7186 csv_version = Version (version = operator_version )
7287 if all (csv_version < fix_version for fix_version in jira_fix_versions ):
7388 LOGGER .info (
74- f"Bug is open: Jira { jira_id } : status is { jira_status } , "
75- f"fix versions { jira_fix_versions } , operator version is { operator_version } "
89+ f"Bug is open: Jira { jira_id } : fix versions { jira_fix_versions } , operator version is { operator_version } "
7690 )
7791 return True
7892
7993 return False
94+
95+
96+ @cache
97+ def is_jira_issue_open (jira_id : str ) -> bool : # skip-unused-code
98+ """
99+ Check if a Jira issue is open based on its status.
100+
101+ Args:
102+ jira_id: Jira issue id (e.g. "RHOAIENG-52129").
103+
104+ Returns:
105+ True if the issue status is not in closed/resolved/testing.
106+ True if Jira is unreachable (assumes issue is open).
107+ """
108+ try :
109+ jira_status = get_jira_issue_fields (jira_id = jira_id ).status .name .lower ()
110+ except NewConnectionError , JIRAError , RequestsConnectionError :
111+ LOGGER .warning (f"Failed to get Jira issue { jira_id } , assuming it is open" )
112+ return True
113+
114+ is_open = jira_status not in JIRA_CLOSED_STATUSES
115+ LOGGER .info (f"Jira { jira_id } : status={ jira_status } , open={ is_open } " )
116+ return is_open
0 commit comments