Skip to content

Commit fb4ce98

Browse files
committed
Add Jira-Database data pump
1 parent 4a94c56 commit fb4ce98

File tree

5 files changed

+118
-21
lines changed

5 files changed

+118
-21
lines changed

__main__.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import sys
33

44
from github import GithubClient
5-
from jira import Jira
5+
from jira import JiraClient
66
from testrail import TestRailClient
77
from utils.constants import PROJECTS_ABBREV, REPORT_TYPES
88

@@ -54,8 +54,8 @@ def main():
5454
h.github_issue_regression(args.project)
5555
h = GithubClient()
5656
if args.report_type == 'jira-qa-requests':
57-
h = Jira()
58-
h.filters()
57+
h = JiraClient()
58+
h.jira_qa_requests()
5959

6060

6161
if __name__ == '__main__':

database.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ class ReportGithubIssues(Base):
3535
__table__ = Table('report_github_issues', Base.metadata, autoload=True)
3636

3737

38+
class ReportJiraQARequests(Base):
39+
__table__ = Table('report_jira_qa_requests', Base.metadata, autoload=True) # noqa
40+
41+
3842
class Database:
3943

4044
def __init__(self):

jira.py

Lines changed: 85 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
11
import os
22
import sys
3+
import json
34

4-
from lib.jira_conn import JiraAPIClient
5+
import pandas as pd
56

7+
from lib.jira_conn import JiraAPIClient
8+
from database import (
9+
Database,
10+
ReportJiraQARequests
11+
)
12+
from utils.datetime_utils import DatetimeUtils as dt
613

714
# JQL query All QA Requests since 2022 filter_id: 13856
815
FILTER_ID_ALL_REQUESTS_2022 = "13856"
@@ -32,6 +39,81 @@ def __init__(self):
3239
# API: Filters
3340
def filters(self):
3441
query = JQL_QUERY + FILTER_ID_ALL_REQUESTS_2022 + '&fields=' \
35-
+ DEFAULT_COLUMNS + STORY_POINTS + FIREFOX_RELEASE_TRAIN \
36-
+ ENGINEERING_TEAM + '&' + MAX_RESULT
42+
+ DEFAULT_COLUMNS + ',' + STORY_POINTS + ',' + FIREFOX_RELEASE_TRAIN \
43+
+ ',' + ENGINEERING_TEAM + '&' + MAX_RESULT
44+
3745
return self.client.get_search(query)
46+
47+
48+
class JiraClient(Jira):
49+
def __init__(self):
50+
super().__init__()
51+
self.db = DatabaseJira()
52+
53+
def jira_qa_requests(self):
54+
payload = self.filters()
55+
56+
data_frame = self.db.report_jira_qa_requests_payload(payload)
57+
print(data_frame)
58+
59+
self.db.report_jira_qa_requests_insert(data_frame)
60+
61+
62+
class DatabaseJira(Database):
63+
64+
def __init__(self):
65+
super().__init__()
66+
self.db = Database()
67+
68+
def report_jira_qa_requests_payload(self, payload):
69+
# Normalize the JSON data
70+
df = pd.json_normalize(payload, sep='_')
71+
72+
# Check if 'jira_assignee_username' exists, if not use 'alternative_assignee_emailAddress'
73+
if 'fields_assignee_emailAddress' not in df.columns:
74+
df['fields_assignee_emailAddress'] = df.get('fields_assignee', "None")
75+
else:
76+
df['fields_assignee_emailAddress'] = df['fields_assignee_emailAddress'].fillna("Not Assigned")
77+
78+
# Drop the alternative column if it exists
79+
if 'fields_assignee' in df.columns:
80+
df.drop(columns=['fields_assignee'], inplace=True)
81+
82+
# Select specific columns
83+
selected_columns = {
84+
'key': 'jira_key',
85+
'fields_summary': 'jira_summary',
86+
'fields_created': 'jira_created_at',
87+
'fields_customfield_10155_value': 'jira_firefox_release_train',
88+
'fields_customfield_10134_value': 'jira_engineering_team',
89+
'fields_customfield_10037': 'jira_story_points',
90+
'fields_status_name': 'jira_status',
91+
'fields_assignee_emailAddress': 'jira_assignee_username',
92+
'fields_labels': 'jira_labels'
93+
}
94+
95+
#Select specific columns
96+
df_selected = df[selected_columns.keys()]
97+
98+
# Rename columns
99+
df_selected = df_selected.rename(columns=selected_columns)
100+
101+
df_selected['jira_created_at'] = df_selected['jira_created_at'].apply(dt.convert_to_utc)
102+
103+
# Join list of labels into a single string
104+
df_selected['jira_labels'] = df_selected['jira_labels'].apply(lambda x: ','.join(x) if isinstance(x, list) else x)
105+
106+
return df_selected
107+
108+
109+
def report_jira_qa_requests_insert(self, payload):
110+
pass
111+
# TBD
112+
# This is the way used in testrail.py
113+
# report = ReportJiraQARequests(payload)
114+
115+
# This is the only way working locally to insert data
116+
# payload.to_sql('report_jira_qa_requests', con=engine, if_exists='append', index=False)
117+
118+
# session.add(report)
119+
# session.commit()

lib/jira_conn.py

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
88
Copyright Atlassian developer. See license.md for details.
99
"""
10+
import json
1011
import requests
1112

1213
from requests.auth import HTTPBasicAuth
@@ -37,32 +38,35 @@ def __send_request(self, method, query):
3738

3839
# Store all results
3940
all_results = []
41+
params = {}
4042

4143
headers = {"Content-Type": "application/json"}
4244

4345
# Pagination variables
44-
start_at = 0
4546
max_results = 100
46-
total = 1 # Initial value greater than start_at to enter the loop
47+
total = None
48+
params['startAt'] = 0
4749

48-
while start_at < total:
50+
while True:
4951
# Send GET request
5052
response = requests.get(
5153
url,
5254
headers=headers,
53-
auth=HTTPBasicAuth(self.user, self.password))
54-
55-
if response.status_code == 200:
56-
data = response.json()
57-
all_results.extend(data['issues'])
58-
total = data['total'] # Update total based on the response
59-
start_at += max_results # Move to the next page
60-
else:
61-
print(f"Failed to fetch data: {response.status_code}")
62-
print(response.text)
55+
auth=HTTPBasicAuth(self.user, self.password),
56+
params=params)
57+
58+
data = response.json()
59+
all_results.extend(data['issues'])
60+
if total is None:
61+
total = data['total']
62+
63+
# Increment the startAt parameter
64+
params['startAt'] += max_results
65+
66+
# Check if we've retrieved all results
67+
if params['startAt'] >= total:
6368
break
6469

6570
# Print the total number of issues retrieved
6671
print(f"Total issues retrieved: {len(all_results)}")
67-
print(data)
68-
return data
72+
return all_results

utils/datetime_utils.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import pytz
2+
13
from datetime import datetime, timedelta
24

35

@@ -16,6 +18,11 @@ def convert_epoch_to_datetime(int_epoch_date):
1618
ts = datetime.fromtimestamp(int_epoch_date)
1719
return ts.strftime(format_date)
1820

21+
def convert_to_utc(datetime_str):
22+
"""Convert datetime string with timezone offset to UTC."""
23+
dt = datetime.strptime(datetime_str, "%Y-%m-%dT%H:%M:%S.%f%z")
24+
return dt.astimezone(pytz.UTC)
25+
1926
def start_date(num_days, end_date=''):
2027
""" given num_days, calculate a start_date
2128
given an end_date (default: now), calculate a start date num_days

0 commit comments

Comments
 (0)