Coverage for suhteita/ticket_system_actions.py: 100.00%
125 statements
« prev ^ index » next coverage.py v7.4.1, created at 2024-02-04 22:42:46 +00:00
« prev ^ index » next coverage.py v7.4.1, created at 2024-02-04 22:42:46 +00:00
1"""Actions on ticket system instances."""
3import copy
4import datetime as dti
5from typing import Dict, List, Tuple, no_type_check
7from atlassian import Jira # type: ignore
9from suhteita import IS_CLOUD, TOKEN, TS_FORMAT_PAYLOADS, Clocking, log
12def login(target_url: str, user: str, password: str = TOKEN, is_cloud: bool = IS_CLOUD) -> Tuple[Clocking, Jira]:
13 """DRY."""
14 start_time = dti.datetime.now(tz=dti.timezone.utc)
15 service = Jira(url=target_url, username=user, password=password, cloud=is_cloud)
16 end_time = dti.datetime.now(tz=dti.timezone.utc)
17 clocking: Clocking = (
18 start_time.strftime(TS_FORMAT_PAYLOADS),
19 (end_time - start_time).microseconds,
20 end_time.strftime(TS_FORMAT_PAYLOADS),
21 )
22 return clocking, service
25def get_server_info(service: Jira) -> Tuple[Clocking, object]:
26 """DRY."""
27 start_time = dti.datetime.now(tz=dti.timezone.utc)
28 data = copy.deepcopy(service.get_server_info(True))
29 end_time = dti.datetime.now(tz=dti.timezone.utc)
30 clocking: Clocking = (
31 start_time.strftime(TS_FORMAT_PAYLOADS),
32 (end_time - start_time).microseconds,
33 end_time.strftime(TS_FORMAT_PAYLOADS),
34 )
35 return clocking, data
38def get_all_projects(service: Jira) -> Tuple[Clocking, List[Dict[str, str]]]:
39 """DRY."""
40 start_time = dti.datetime.now(tz=dti.timezone.utc)
41 projects = copy.deepcopy(service.get_all_projects(included_archived=None))
42 end_time = dti.datetime.now(tz=dti.timezone.utc)
43 clocking: Clocking = (
44 start_time.strftime(TS_FORMAT_PAYLOADS),
45 (end_time - start_time).microseconds,
46 end_time.strftime(TS_FORMAT_PAYLOADS),
47 )
48 return clocking, projects
51@no_type_check
52def create_issue(service: Jira, project: str, ts: str, description: str) -> Tuple[Clocking, str]:
53 """DRY."""
54 fields = {
55 'project': {'key': project},
56 'issuetype': {'name': 'Task'},
57 'summary': f'From REST we create at {ts}',
58 'description': description,
59 }
60 start_time = dti.datetime.now(tz=dti.timezone.utc)
61 created = copy.deepcopy(service.issue_create(fields=fields))
62 end_time = dti.datetime.now(tz=dti.timezone.utc)
63 clocking: Clocking = (
64 start_time.strftime(TS_FORMAT_PAYLOADS),
65 (end_time - start_time).microseconds,
66 end_time.strftime(TS_FORMAT_PAYLOADS),
67 )
68 return clocking, created['key']
71@no_type_check
72def issue_exists(service: Jira, issue_key: str) -> Tuple[Clocking, bool]:
73 """DRY."""
74 start_time = dti.datetime.now(tz=dti.timezone.utc)
75 exists = copy.deepcopy(service.issue_exists(issue_key))
76 end_time = dti.datetime.now(tz=dti.timezone.utc)
77 clocking: Clocking = (
78 start_time.strftime(TS_FORMAT_PAYLOADS),
79 (end_time - start_time).microseconds,
80 end_time.strftime(TS_FORMAT_PAYLOADS),
81 )
82 return clocking, exists
85@no_type_check
86def get_issue_status(service: Jira, issue_key: str) -> Tuple[Clocking, str]:
87 """DRY."""
88 start_time = dti.datetime.now(tz=dti.timezone.utc)
89 status = copy.deepcopy(service.get_issue_status(issue_key))
90 end_time = dti.datetime.now(tz=dti.timezone.utc)
91 clocking: Clocking = (
92 start_time.strftime(TS_FORMAT_PAYLOADS),
93 (end_time - start_time).microseconds,
94 end_time.strftime(TS_FORMAT_PAYLOADS),
95 )
96 return clocking, status
99def set_issue_status(service: Jira, issue_key: str, status: str) -> Tuple[Clocking, object]:
100 """DRY."""
101 start_time = dti.datetime.now(tz=dti.timezone.utc)
102 response = copy.deepcopy(service.set_issue_status(issue_key, status))
103 end_time = dti.datetime.now(tz=dti.timezone.utc)
104 clocking: Clocking = (
105 start_time.strftime(TS_FORMAT_PAYLOADS),
106 (end_time - start_time).microseconds,
107 end_time.strftime(TS_FORMAT_PAYLOADS),
108 )
109 return clocking, response
112def load_issue(service: Jira, issue_key: str) -> Tuple[Clocking, object]:
113 """DRY."""
114 start_time = dti.datetime.now(tz=dti.timezone.utc)
115 data = copy.deepcopy(service.issue(issue_key))
116 end_time = dti.datetime.now(tz=dti.timezone.utc)
117 clocking: Clocking = (
118 start_time.strftime(TS_FORMAT_PAYLOADS),
119 (end_time - start_time).microseconds,
120 end_time.strftime(TS_FORMAT_PAYLOADS),
121 )
122 return clocking, data
125@no_type_check
126def execute_jql(service: Jira, query: str) -> Tuple[Clocking, object]:
127 """DRY."""
128 start_time = dti.datetime.now(tz=dti.timezone.utc)
129 data = copy.deepcopy(service.jql(query))
130 end_time = dti.datetime.now(tz=dti.timezone.utc)
131 clocking: Clocking = (
132 start_time.strftime(TS_FORMAT_PAYLOADS),
133 (end_time - start_time).microseconds,
134 end_time.strftime(TS_FORMAT_PAYLOADS),
135 )
136 return clocking, data
139@no_type_check
140def amend_issue_description(service: Jira, issue_key: str, amendment: str, issue_context) -> Clocking:
141 """DRY."""
142 start_time = dti.datetime.now(tz=dti.timezone.utc)
143 _ = copy.deepcopy(
144 service.update_issue_field(
145 issue_key,
146 fields={'description': f"{issue_context['issues'][0]['fields']['description']}\n{amendment}"},
147 )
148 )
149 end_time = dti.datetime.now(tz=dti.timezone.utc)
150 clocking: Clocking = (
151 start_time.strftime(TS_FORMAT_PAYLOADS),
152 (end_time - start_time).microseconds,
153 end_time.strftime(TS_FORMAT_PAYLOADS),
154 )
155 return clocking
158@no_type_check
159def add_comment(service: Jira, issue_key: str, comment: str) -> Tuple[Clocking, object]:
160 """DRY."""
161 start_time = dti.datetime.now(tz=dti.timezone.utc)
162 response = copy.deepcopy(service.issue_add_comment(issue_key, comment))
163 end_time = dti.datetime.now(tz=dti.timezone.utc)
164 clocking: Clocking = (
165 start_time.strftime(TS_FORMAT_PAYLOADS),
166 (end_time - start_time).microseconds,
167 end_time.strftime(TS_FORMAT_PAYLOADS),
168 )
169 return clocking, response
172def update_issue_field(service: Jira, issue_key: str, labels: List[str]) -> Clocking:
173 """DRY."""
174 start_time = dti.datetime.now(tz=dti.timezone.utc)
175 _ = copy.deepcopy(service.update_issue_field(issue_key, fields={'labels': labels}))
176 end_time = dti.datetime.now(tz=dti.timezone.utc)
177 clocking: Clocking = (
178 start_time.strftime(TS_FORMAT_PAYLOADS),
179 (end_time - start_time).microseconds,
180 end_time.strftime(TS_FORMAT_PAYLOADS),
181 )
182 return clocking
185def create_duplicates_issue_link(
186 service: Jira, duplicate_issue_key: str, original_issue_key: str
187) -> Tuple[Clocking, object]:
188 """DRY."""
189 data = {
190 'type': {'name': 'Duplicate'},
191 'inwardIssue': {'key': duplicate_issue_key},
192 'outwardIssue': {'key': original_issue_key},
193 'comment': {
194 'body': f'{duplicate_issue_key} truly duplicates {original_issue_key}!',
195 },
196 }
197 start_time = dti.datetime.now(tz=dti.timezone.utc)
198 response = copy.deepcopy(service.create_issue_link(data))
199 end_time = dti.datetime.now(tz=dti.timezone.utc)
200 clocking: Clocking = (
201 start_time.strftime(TS_FORMAT_PAYLOADS),
202 (end_time - start_time).microseconds,
203 end_time.strftime(TS_FORMAT_PAYLOADS),
204 )
205 return clocking, response
208def set_original_estimate(service: Jira, issue_key: str, hours: int) -> Tuple[Clocking, bool]:
209 """DRY."""
210 ok = True
211 try:
212 start_time = dti.datetime.now(tz=dti.timezone.utc)
213 _ = copy.deepcopy(
214 service.update_issue_field(issue_key, fields={'timetracking': {'originalEstimate': f'{hours}h'}})
215 )
216 end_time = dti.datetime.now(tz=dti.timezone.utc)
217 except Exception as err: # noqa
218 end_time = dti.datetime.now(tz=dti.timezone.utc)
219 ok = False
220 log.error(f'Failed setting "{issue_key}".timetracking.originalEstimate to {hours} with (next error log line):')
221 log.error(f'cont. ({err})')
222 clocking: Clocking = (
223 start_time.strftime(TS_FORMAT_PAYLOADS),
224 (end_time - start_time).microseconds,
225 end_time.strftime(TS_FORMAT_PAYLOADS),
226 )
227 return clocking, ok
230def create_component(service: Jira, project: str, name: str, description: str) -> Tuple[Clocking, str, str, object]:
231 """DRY."""
232 comp_data = {
233 'project': project,
234 'description': description,
235 'name': name,
236 'assigneeType': 'UNASSIGNED',
237 }
238 start_time = dti.datetime.now(tz=dti.timezone.utc)
239 comp_create_resp = copy.deepcopy(service.create_component(comp_data))
240 end_time = dti.datetime.now(tz=dti.timezone.utc)
241 clocking: Clocking = (
242 start_time.strftime(TS_FORMAT_PAYLOADS),
243 (end_time - start_time).microseconds,
244 end_time.strftime(TS_FORMAT_PAYLOADS),
245 )
246 comp_id = comp_create_resp['id']
247 return clocking, comp_id, name, service.component(comp_id)
250def relate_issue_to_component(service: Jira, issue_key: str, comp_id: str, comp_name: str) -> Tuple[Clocking, bool]:
251 """DRY."""
252 ok = True
253 try:
254 start_time = dti.datetime.now(tz=dti.timezone.utc)
255 _ = copy.deepcopy(service.update_issue_field(issue_key, fields={'components': [{'name': comp_name}]}))
256 end_time = dti.datetime.now(tz=dti.timezone.utc)
257 except Exception as err: # noqa
258 ok = False
259 end_time = dti.datetime.now(tz=dti.timezone.utc)
260 log.error(f'Not able to set component for issue: ({err}) Cleaning up - deleting component ID={comp_id}')
261 service.delete_component(comp_id)
262 clocking: Clocking = (
263 start_time.strftime(TS_FORMAT_PAYLOADS),
264 (end_time - start_time).microseconds,
265 end_time.strftime(TS_FORMAT_PAYLOADS),
266 )
267 return clocking, ok