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

1"""Actions on ticket system instances.""" 

2 

3import copy 

4import datetime as dti 

5from typing import Dict, List, Tuple, no_type_check 

6 

7from atlassian import Jira # type: ignore 

8 

9from suhteita import IS_CLOUD, TOKEN, TS_FORMAT_PAYLOADS, Clocking, log 

10 

11 

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 

23 

24 

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 

36 

37 

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 

49 

50 

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'] 

69 

70 

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 

83 

84 

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 

97 

98 

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 

110 

111 

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 

123 

124 

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 

137 

138 

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 

156 

157 

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 

170 

171 

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 

183 

184 

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 

206 

207 

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 

228 

229 

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) 

248 

249 

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